【Eureka技术指南】「SpringCloud」从源码层面让你认识Eureka工作流程和运作机制(上)

news2024/10/7 10:22:45

前言介绍

了解到了SpringCloud,大家都应该知道注册中心,而对于我们从过去到现在,SpringCloud中用的最多的注册中心就是Eureka了,所以深入Eureka的原理和源码,接下来我们要进行讲解下eureka的源码分析,由此应运而产生的本章节的内容。

基本原理

  1. Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到
  2. Eureka Client 是一个Java 客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的、使用轮询负载算法的负载均衡器
  3. 在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒),如果Eureka Server在多个心跳周期(默认3个周期)没有收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)
  4. Eureka Server之间将会通过复制的方式完成数据的同步;
  5. Eureka Client具有缓存的机制,即使所有的Eureka Server都挂掉的话,客户端依然可以利用缓存中的信息消费其它服务的API;

启动流程分析

从EurekaServer 启动的流程日志入手分析:

2021-01-21 18:14:17.635  INFO 5288 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'environmentManager': registering with JMX server as MBean [org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager]
2021-01-21 18:14:17.650  INFO 5288 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'restartEndpoint': registering with JMX server as MBean [org.springframework.cloud.context.restart:name=restartEndpoint,type=RestartEndpoint]
2021-01-21 18:14:17.661  INFO 5288 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'refreshScope': registering with JMX server as MBean [org.springframework.cloud.context.scope.refresh:name=refreshScope,type=RefreshScope]
2021-01-21 18:14:17.674  INFO 5288 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'configurationPropertiesRebinder': registering with JMX server as MBean [org.springframework.cloud.context.properties:name=configurationPropertiesRebinder,context=335b5620,type=ConfigurationPropertiesRebinder]
2021-01-21 18:14:17.683  INFO 5288 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'refreshEndpoint': registering with JMX server as MBean [org.springframework.cloud.endpoint:name=refreshEndpoint,type=RefreshEndpoint]
2021-01-21 18:14:17.926  INFO 5288 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2021-01-21 18:14:17.927  INFO 5288 --- [           main] c.n.e.EurekaDiscoveryClientConfiguration : Registering application unknown with eureka with status UP
2021-01-21 18:14:17.927  INFO 5288 --- [      Thread-10] o.s.c.n.e.server.EurekaServerBootstrap   : Setting the eureka configuration..

2021-01-21 18:14:17.948  INFO 5288 --- [      Thread-10] o.s.c.n.e.server.EurekaServerBootstrap   : isAws returned false
2021-01-21 18:14:17.949  INFO 5288 --- [      Thread-10] o.s.c.n.e.server.EurekaServerBootstrap   : Initialized server context
2021-01-21 18:14:17.949  INFO 5288 --- [      Thread-10] c.n.e.r.PeerAwareInstanceRegistryImpl    : Got 1 instances from neighboring DS node
2021-01-21 18:14:17.949  INFO 5288 --- [      Thread-10] c.n.e.r.PeerAwareInstanceRegistryImpl    : Renew threshold is: 1
2021-01-21 18:14:17.949  INFO 5288 --- [      Thread-10] c.n.e.r.PeerAwareInstanceRegistryImpl    : Changing status to UP
2021-01-21 18:14:17.958  INFO 5288 --- [      Thread-10] e.s.EurekaServerInitializerConfiguration : Started Eureka Server
2021-01-21 18:14:18.019  INFO 5288 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8761 (http)
2021-01-21 18:14:18.020  INFO 5288 --- [           main] c.n.e.EurekaDiscoveryClientConfiguration : Updating port to 8761
2021-01-21 18:14:18.023  INFO 5288 --- [           main] c.s.cloud.EurekaServerApplication        : Started EurekaServerApplication in 8.299 seconds (JVM running for 8.886)
复制代码

Eureka微服务已启动.

日志打印"Setting the eureka configuration…",eureka开始进行配置,说不定也许就是Eureka Server流程启动的开始呢?我们抱着怀疑的心态进入这行日志打印的EurekaServerBootstrap类去看看。

EurekaServerBootstrap类

看看,看这个类的名字,见名知意,应该就是 EurekaServer 的启动类了:

protected void initEurekaEnvironment() throws Exception {
	log.info("Setting the eureka configuration..");
}
复制代码
initEurekaEnvironment方法

我们看到日志在initEurekaEnvironment方法中被打印出来,然后我顺着这个方法寻找该方法被调用的地方;

public void contextInitialized(ServletContext context) {
	try {
		initEurekaEnvironment();
		initEurekaServerContext();
		context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
	}
	catch (Throwable e) {
		log.error("Cannot bootstrap eureka server :", e);
		throw new RuntimeException("Cannot bootstrap eureka server :", e);
	}
}
复制代码
contextInitialized

接着发现contextInitialized这个方法里面调用了initEurekaEnvironment 方法,接着我们再往上层寻找被调用的地方;

EurekaServerInitializerConfiguration

接着我们看到 EurekaServerInitializerConfiguration 类中有个 start 方法,该方法创建了一个线程来后台执行 EurekaServer 的初始化流程;

进入 EurekaServerInitializerConfiguration 方法,看看这个所谓的 EurekaServer 初始化配置做了哪些事情?

@Override
public void start() {
	new Thread(new Runnable() {
		@Override
		public void run() {
			try {

				eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
				log.info("Started Eureka Server");
				publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
				EurekaServerInitializerConfiguration.this.running = true;
				publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
			}
			catch (Exception ex) {

				log.error("Could not initialize Eureka servlet context", ex);
			}
		}
	}).start();
}
复制代码
  • 看到 log.info(“Started Eureka Server”); 这行代码,相信大家已经释然了,这里就是所谓的启动了 EurekaServer 了,其实也就是 eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext) 初始化了一些我们未知的东西;
  • 当打印完启动Eureka Server日志后,调用了两次 publish 方法,该方法最终调用的是this.applicationContext.publishEvent(event) 方法,目的是利用Spring中ApplicationContext对事件传递性质,事件发布者(applicationContext)来发布事件(event),但是缺少的是监听者,其实你仔细搜索下代码,发现好像没有地方对 EurekaServerStartedEvent、EurekaRegistryAvailableEvent 进行监听。
  • 然后找到 EurekaServerStartedEvent 所在的目录下,EurekaInstanceCanceledEvent、EurekaInstanceRegisteredEvent、EurekaInstanceRenewedEvent、EurekaRegistryAvailableEvent、EurekaServerStartedEvent 有这么几个事件的类,服务下线事件、服务注册事件、服务续约事件、注册中心启动事件、Eureka Server启动事件,这么几个事件都没有被监听。
  • 像这样 @EventListener public void listen(EurekaInstanceCanceledEvent event) {下线逻辑 },添加EventListener 监听注解,就可以在我们自己的代码逻辑中收到这个事件的回调了,所以想想SpringCloud还是挺机制的,提供回调接口让我们自己实现自己的业务逻辑,真心不错;
  • 那么反过来想想,为啥会无缘无故 start 方法就被调用了呢?那么反向继续向上找调用 start 方法的地方,结果找到了DefaultLifecycleProcessor类的doStart方法调用了 bean.start();

DefaultLifecycleProcessor

EurekaServerInitializerConfiguration.start 方法是如何被触发的?

private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {

	Lifecycle bean = lifecycleBeans.remove(beanName);
	if (bean != null && !this.equals(bean)) {
		String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName);
		for (String dependency : dependenciesForBean) {
			doStart(lifecycleBeans, dependency, autoStartupOnly);
		}
		if (!bean.isRunning() &&
				(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
			if (logger.isDebugEnabled()) {
				logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]");
			}
			try {
				bean.start();
			}
			catch (Throwable ex) {
				throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Successfully started bean '" + beanName + "'");
			}
		}
	}
}
复制代码

看到在 bean.isRunning 等一系列状态的判断下才去调用 bean.start() 方法的,我们再往上寻找被调用地方;

public void start() {

	if (this.members.isEmpty()) {
		return;
	}
	if (logger.isInfoEnabled()) {
		logger.info("Starting beans in phase " + this.phase);
	}
	Collections.sort(this.members);
	for (LifecycleGroupMember member : this.members) {
		if (this.lifecycleBeans.containsKey(member.name)) {
			doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
		}
	}
}
复制代码

该类是DefaultLifecycleProcessor中内部类LifecycleGroup的一个方法,再往上寻找调用方;

private void startBeans(boolean autoStartupOnly) {
	Map lifecycleBeans = getLifecycleBeans();
	Map phases = new HashMap();
	for (Map.Entryextends Lifecycle> entry : lifecycleBeans.entrySet()) {
		Lifecycle bean = entry.getValue();
		if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
			int phase = getPhase(bean);
			LifecycleGroup group = phases.get(phase);
			if (group == null) {
				group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
				phases.put(phase, group);
			}
			group.add(entry.getKey(), bean);
		}
	}
	if (phases.size() > 0) {
		List keys = new ArrayList(phases.keySet());
		Collections.sort(keys);
		for (Integer key : keys) {
			phases.get(key).start();
		}
	}
}
复制代码
  • startBeans 属于 DefaultLifecycleProcessor 类的一个私有方法,startBeans 方法第一行就是获取 getLifecycleBeans() 生命周期Bean对象,由此可见似乎 Eureka Server 之所以会被启动,是不是实现了某个接口或者重写了某个方法,才会导致由于容易在初始化的过程中因调用某些特殊方法或者某些类才启动的,因此我们回头去看看 EurekaServerInitializerConfiguration 这个类;
  • 结果发现 EurekaServerInitializerConfiguration 这个类实现了 SmartLifecycle 这么样的一个接口,而 SmartLifecycle 接口又继承了 Lifecycle 生命周期接口类,所以真想已经重见天日了,原来是实现了 Lifecycle 这样的一个接口,然后实现了 start 方法,因此 Eureka Server 就这么稀里糊涂的就被莫名其妙的启动起来了?

我们之前仅仅只是通过了日志来逆向分析,但是我们是不是忘了我们本应该标志是Eureka Server的这个注解了呢?没错,我们在分析的过程中 已经将 @EnableEurekaServer 这个注解遗忘了,那么我们现在先回到这个注解类来看看;

EnableEurekaServer

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerConfiguration.class)
public @interface EnableEurekaServer {}
复制代码

我们不难发现 EnableEurekaServer 类上有个 @Import 注解,引用了一个 class 文件,由此我们进入观察;

EurekaServerConfiguration 类看看,看名称的话,理解的意思大概就是 Eureka Server 配置类;

  • 果不其然,这个类有很多 @Bean、@Configuration 注解过的方法,那是不是我们可以认为刚才 3.1~3.4 的推论是不是就是由于被实例化了这么一个 Bean,然后就慢慢的调用到了 start 方法了呢?
  • 搜索 “Bootstrap” 字样,还真发现了有这么一个方法;

public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
		EurekaServerContext serverContext) {
	return new EurekaServerBootstrap(this.applicationInfoManager,
			this.eurekaClientConfig, this.eurekaServerConfig, registry,
			serverContext);
}
复制代码
  • 既然有这么一个 Bean,那么是不是和刚开始顺着日志逆向分析也是有一定道理的,没有这么一个Bean的存在,那么 DefaultLifecycleProcessor.startBeans 方法中 getLifecycleBeans 的这个也就没那么顺畅被找到了呢?不过我的猜想是这样的,本人没有将源码下载下来,将 eurekaServerBootstrap 方法中的 @Bean 注解注释掉试试,不过推理起来也八九不离十,这个疑问悬念就留给大家尝试尝试吧;
  • 既然找到了一个 @Bean 注解过的方法,那我们再找找其他的一些被注解过的方法,比如一些通用全局用的类似词眼,比如 Context,Bean,Init、Server 之类的;

public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
		PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
	return new DefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs,
			registry, peerEurekaNodes, this.applicationInfoManager);
}

public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
		ServerCodecs serverCodecs) {
	return new PeerEurekaNodes(registry, this.eurekaServerConfig,
			this.eurekaClientConfig, serverCodecs, this.applicationInfoManager);
}

public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
		ServerCodecs serverCodecs) {
	this.eurekaClient.getApplications();
	return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
			serverCodecs, this.eurekaClient,
			this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(),
			this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}

public EurekaController eurekaController() {
	return new EurekaController(this.applicationInfoManager);
}
复制代码
  • DefaultEurekaServerContext.initialize 初始化了一些东西,现在还不知道干啥用的,先放这里,打上断点;
  • PeerEurekaNodes.start 方法,又是一个 start 方法,但是该类没有实现任何类,姑且先放这里,打上断点;
  • InstanceRegistry.register 方法,而且还有几个呢,可能是客户端注册用的,也先放这里,都打上断点,或者将 这个类的所有方法都断点上,断点打完后发现有注册的,有续约的,有注销的;
  • 打完这些断点后,感觉没有思路了,索性就断点跑一把,看看有什么新的发现点;
【分析一】:DefaultEurekaServerContext.initialize 方法被调用了,证实了刚才想法,EurekaServerConfiguration 不是白写的,还是有它的作用的;

public void initialize() throws Exception {
    logger.info("Initializing ...");
    peerEurekaNodes.start();
    registry.init(peerEurekaNodes);
    logger.info("Initialized");
}

【分析二】:进入 initialize 方法中 peerEurekaNodes.start();

public void start() {
    taskExecutor = Executors.newSingleThreadScheduledExecutor(
            new ThreadFactory() {

                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r, "Eureka-PeerNodesUpdater");
                    thread.setDaemon(true);
                    return thread;
                }
            }
    );
    try {
        updatePeerEurekaNodes(resolvePeerUrls());
        Runnable peersUpdateTask = new Runnable() {

            public void run() {
                try {
                    updatePeerEurekaNodes(resolvePeerUrls());
                } catch (Throwable e) {
                    logger.error("Cannot update the replica Nodes", e);
                }

            }
        };

        taskExecutor.scheduleWithFixedDelay(
                peersUpdateTask,
                serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
                serverConfig.getPeerEurekaNodesUpdateIntervalMs(),
                TimeUnit.MILLISECONDS
        );
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
    for (PeerEurekaNode node : peerEurekaNodes) {
        logger.info("Replica node URL:  " + node.getServiceUrl());
    }
}
复制代码
  • start 方法中会看到一个定时调度的任务,updatePeerEurekaNodes(resolvePeerUrls()); 间隔 600000 毫秒,即 10分钟 间隔执行一次服务集群数据同步;
  • 然后断点放走放下走,进入 initialize 方法中 registry.init(peerEurekaNodes);

public void init(PeerEurekaNodes peerEurekaNodes) throws Exception {
    this.numberOfReplicationsLastMin.start();
    this.peerEurekaNodes = peerEurekaNodes;

    initializedResponseCache();

    scheduleRenewalThresholdUpdateTask();

    initRemoteRegionRegistry();

    try {
        Monitors.registerObject(this);
    } catch (Throwable e) {
        logger.warn("Cannot register the JMX monitor for the InstanceRegistry :", e);
    }
}
复制代码

缓存也配置好了,定时任务也配置好了,似乎应该没啥了,那么我们把断点放开,看看下一步会走到哪里?

EurekaServerInitializerConfiguration.start。

  • 先是 DefaultLifecycleProcessor.doStart 方法进断点,然后才是 EurekaServerInitializerConfiguration.start 方法进断点;
  • 再一次证明刚刚的逆向分析仅仅只是缺了个从头EnableEurekaServer分析罢了,但是最终方法论分析思路还是对的,由于开始分析过这里,然而我们就跳过,继续放开断点向后继续看看;

InstanceRegistry.openForTraffic

  • 【这不就是我们刚才在 “步骤3.7之分析七” 打的断点么?看下堆栈信息,正是 “步骤3.2之分析一” 中 initEurekaServerContext 方法中有这么一句 this.registry.openForTraffic(this.applicationInfoManager, registryCount); 调用到了,因果轮回,代码千变万化,打上断点还有有好处的,结果还是回到了开始日志逆向分析的地方。

c进入 super.openForTraffic 方法;


public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {

    this.expectedNumberOfRenewsPerMin = count * 2;
    this.numberOfRenewsPerMinThreshold =
            (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
    logger.info("Got " + count + " instances from neighboring DS node");
    logger.info("Renew threshold is: " + numberOfRenewsPerMinThreshold);
    this.startupTime = System.currentTimeMillis();
    if (count > 0) {
        this.peerInstancesTransferEmptyOnStartup = false;
    }
    DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();
    boolean isAws = Name.Amazon == selfName;
    if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) {
        logger.info("Priming AWS connections for all replicas..");
        primeAwsReplicas(applicationInfoManager);
    }
    logger.info("Changing status to UP");

    applicationInfoManager.setInstanceStatus(InstanceStatus.UP);

    super.postInit();
}
复制代码
  • 这里主要设置了服务状态,以及开启了定时清理失效节点的定时任务,每分钟扫描一次;

继续放开断点,来到了日志打印 “main] c.n.e.EurekaDiscoveryClientConfiguration : Updating port to 8761” 的EurekaDiscoveryClientConfiguration 类中 onApplicationEvent 方法。


public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {

	int localPort = event.getEmbeddedServletContainer().getPort();
	if (this.port.get() == 0) {
		log.info("Updating port to " + localPort);
		this.port.compareAndSet(0, localPort);
		start();
	}
}
复制代码
  • 设置端口,当看到 Updating port to 8761 这样的日志打印出来的话,说明 Eureka Server 整个启动也就差不多Over了。现在回头看看,发现分析了不少的方法和流程,有种感觉被掏空的感觉了。

总结 EurekaServer 启动时候大概干了哪些事情?

1、初始化Eureka环境,Eureka上下文; 2、初始化EurekaServer的缓存 3、启动了一些定时任务,比如充值心跳阈值定时任务,清理失效节点定时任务; 4、更新EurekaServer上电状态,更新EurekaServer端口;

分享资源

资源分享
获取以上资源请访问开源项目 点击跳转

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/856918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle数据迁移

问题描述&#xff1a; oracle数据库的所有表结构、数据、索引等需要需从测试库迁移到正式库。 解决步骤&#xff1a; oracle数据库迁移&#xff0c;主要通过expdp从测试库所在的源服务器将指定的数据表或数据源导出为一个或多个数据文件&#xff08;.dmp文件&#xff09;&…

第五届太原理工大学新生赛(决赛)题解

题解&#xff09; <font colorred>第五届太原理工大学新生赛&#xff08;决赛&#xff09;:star:A.810975:star2:<font colorgreen>题意:cherries:<font colorred>解决思路:pear:代码 :star:<font colorpink>B.hammer玩游戏:star2:<font colorgreen…

STM32--综述

文章目录 前言STM32简介STM32F103C8T6系统结构Keil软件安装注意事项新建工程操作流程 前言 本专栏将学习B站江协科技的STM32入门教程&#xff0c;通过自身理解和对老师的总结所写的博客专栏。 STM32简介 STM32是意法半导体&#xff08;STMicroelectronics&#xff09;公司推…

5.3.10.静态映射表建立过程分析

5.3.10.静态映射表建立过程分析 5.3.10.1、建立映射表的三个关键部分 (1)映射表具体物理地址和虚拟地址的值相关的宏定义 https://blog.csdn.net/liangzuzong/article/details/131994560 (2)映射表建立函数&#xff08;宏定义&#xff09;。该函数负责由(1)中的映射表来建立li…

以太网TCP协议(十二)

目录 一、概述 二、功能 2.1 连接管理 2.2 响应与序列号 2.3 超时重发 2.4 传输单位&#xff1a;段 2.5 窗口控制 2.6 流控制 2.7 拥塞控制 2.8 效率提高 三、报文格式 一、概述 TCP作为一种面向有连接的协议&#xff0c;只有在确认通信对端存在时才会发送数据&…

SD-MTSP:蜘蛛蜂优化算法SWO求解单仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&#xff0c;具有搜索速度快&#xff0c;求解精度高的优势。蜘蛛蜂优化算…

Hugging Face 的文本生成和大语言模型的开源生态

[更新于 2023 年 7 月 23 日: 添加 Llama 2。] 文本生成和对话技术已经出现多年了。早期的挑战在于通过设置参数和分辨偏差&#xff0c;同时控制好文本忠实性和多样性。更忠实的输出一般更缺少创造性&#xff0c;并且和原始训练数据更加接近&#xff0c;也更不像人话。最近的研…

论文研读-SIMD系列-基于分区的SIMD处理及在列存数据库系统中的应用

基于分区的SIMD处理及在列存数据库系统中的应用 单指令多数据&#xff08;SIMD&#xff09;范式称为列存数据库系统中优化查询处理的核心原则。到目前为止&#xff0c;只有LOAD/STORE指令被认为足够高效&#xff0c;可以实现预期的加速&#xff0c;并且认为需要尽可能避免GATHE…

Sentieon | 每周文献-Benchmark and Method Study(基准与方法研究)-第八期

基准与方法研究系列文章-1 标题&#xff08;英文&#xff09;&#xff1a; Standardized Comparison of Different DNA Sequencing Platforms 标题&#xff08;中文&#xff09;&#xff1a; 不同 DNA 测序平台的标准化比较 发表期刊&#xff1a; Clinical Chemistry 作者单…

leetCode刷题记录1

文章目录 hot100题200. 岛屿数量206. 反转链表207. 课程表208. 实现 Trie (前缀树)★ Student[] strArr new Student[26];//真的只是创建了引用数组 只是new了数组存放引用的内存 并没有真的new对象内存 215. 数组中的第K个最大元素221. 最大正方形226. 翻转二叉树234. 回文链表…

Java定时算法实现与应用(最小堆、时间轮)

文章目录 一、定时算法 概述二、最小堆算法1、概述2、Java实现最小堆算法&#xff08;1&#xff09;Timer使用&#xff08;2&#xff09;源码分析 3、应用 三、 时间轮算法1、概述2、Java实现时间轮算法 一、定时算法 概述 系统或者项目中难免会遇到各种需要自动去执行的任务&…

免费小程序商城搭建之b2b2c o2o 多商家入驻商城 直播带货商城 电子商务b2b2c o2o 多商家入驻商城 直播带货商城 电子商务 bbc

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端…

视频音频怎么提取成MP3?教你几种简单提取方法

提取视频音频并将其转换为MP3格式有很多好处。首先&#xff0c;MP3格式是一种广泛支持的音频格式&#xff0c;可以在几乎所有设备上播放&#xff0c;包括计算机、手机和音乐播放器。这意味着您可以在任何设备上随时随地享受音频内容&#xff0c;而不必担心格式兼容性问题。那么…

Win11中使用pip或者Cython报错 —— error: Microsoft Visual C++ 14.0 is required.

第一步&#xff1a;下载Visual Studio 2019 下载地址&#xff1a; https://learn.microsoft.com/zh-cn/visualstudio/releases/2019/release-notes 第二步&#xff1a;安装组件 选择单个组件&#xff0c;勾选以下两个组件 其他错误&#xff1a; 无法打开文件“python37.li…

触控触感方案原厂18按键触摸芯片电路图

VK3618I具有18个触摸按键&#xff0c;可用来检测外部触摸按键上人手的触摸动作。该芯片具有较 高的集成度&#xff0c;仅需极少的外部组件便可实现触摸按键的检测。 提供了2组I2C输出功能&#xff0c;1个INT中断输出脚&#xff0c;2组I2C脚和INT可并联&#xff0c;每组单键输出…

【腾讯云 Cloud Studio 实战训练营】快速构建React完成点餐H5页面

一&#xff0c;前言 1.1 相关链接 官网地址&#xff1a;Cloud Studio 官方文档地址&#xff1a;Cloud Studio&#xff08;云端 IDE&#xff09;简介 | Cloud Studio 1.2 Cloud Studio&#xff08;云端 IDE&#xff09;简介 Cloud Studio 是基于浏览器的集成式开发环境&#…

山景DSP芯片可烧录AP8224C2音频处理器方案

AP8224C2高性能32位音频应用处理器AP82系列音频处理器是面向音频应用领域设计的新一代SoC平台产品&#xff0c;适用于传统音响系统、新兴的蓝牙或Wifi 无线音频产品、Sound Bar 和调音台等市场。该处理器在总体架构和系统组成上&#xff0c;充分考虑了音频领域的特点&#xff0…

一个月学通Python(三十四):使用Selenium模拟人工操作及获取网页内容

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3-5章&#xff0c;最短1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教…

【cs61b】学习笔记day2

历史文章目录 【cs61b】学习笔记day1 文章目录 历史文章目录List两个小问题bits声明一个变量引用类型方框和指针表示法数组的实例化链表 SLList List 两个小问题 思考下面两个代码分别输出什么 Walrus a new Walrus(1000, 8.3); Walrus b; b a; b.weight 5; System.out.…

并发编程面试题1

并发编程面试题1 一、原子性高频问题&#xff1a; 1.1 Java中如何实现线程安全? 多线程操作共享数据出现的问题。 锁&#xff1a; 悲观锁&#xff1a;synchronized&#xff0c;lock乐观锁&#xff1a;CAS 可以根据业务情况&#xff0c;选择ThreadLocal&#xff0c;让每个…