SpringClound Eureka 1.9.12 版本源码解析

news/2024/7/23 18:18:34 标签: eureka, 云原生, spring boot, spring cloud, java, spring

Eureka启动,原生启动与SpringCloudEureka启动异同

我们先看看作为原生的EurekaServer启动的过程,作为一个Servlet应用,他的启动入口就是他的主要ServletContextListener类(这里是EurekaBootStrap)的contextInitialized方法
EurekaServerBootstrap

@Override
public void contextInitialized(ServletContextEvent event) {
try {
initEurekaEnvironment();
initEurekaServerContext();

    ServletContext sc = event.getServletContext();
    sc.setAttribute(EurekaServerContext.class.getName(), serverContext);
} catch (Throwable e) {
    logger.error("Cannot bootstrap eureka server :", e);
    throw new RuntimeException("Cannot bootstrap eureka server :", e);
}

}

可以看出主要做了两件事,initEurekaEnvironment()与initEurekaServerContext()
对于initEurekaEnvironment()只是初始化一些必要的环境变量,由于Eureka配置基于Spring的配置中间件Archaius,这些环境变量都是针对这个配置中间件使用的。
initEurekaServerContext()是我们重点需要关心的,它初始化了EurekaServer需要的所有组件:

protected void initEurekaServerContext() throws Exception {
EurekaServerConfig eurekaServerConfig = new DefaultEurekaServerConfig();

//设置json与xml序列化工具
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
logger.info("Initializing the eureka client...");
logger.info(eurekaServerConfig.getJsonCodecName());
ServerCodecs serverCodecs = new DefaultServerCodecs(eurekaServerConfig);


ApplicationInfoManager applicationInfoManager = null;

//初始化EurekaClient,EurekaClient用来与其他EurekaServer进行交互
//有可能通过guice初始化Eureka,这时eurekaClient和ApplicationInfoManager通过依赖注入先被初始化
if (eurekaClient == null) {
    EurekaInstanceConfig instanceConfig = isCloud(ConfigurationManager.getDeploymentContext())
            ? new CloudInstanceConfig()
            : new MyDataCenterInstanceConfig();

    applicationInfoManager = new ApplicationInfoManager(
            instanceConfig, new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());

    EurekaClientConfig eurekaClientConfig = new DefaultEurekaClientConfig();
    eurekaClient = new DiscoveryClient(applicationInfoManager, eurekaClientConfig);
} else {
    applicationInfoManager = eurekaClient.getApplicationInfoManager();
}

//初始化PeerAwareInstanceRegistry, 这个类里面的方法就是与集群内其他EurekaServer实例保持业务同步的机制
PeerAwareInstanceRegistry registry;
if (isAws(applicationInfoManager.getInfo())) {
    registry = new AwsInstanceRegistry(
            eurekaServerConfig,
            eurekaClient.getEurekaClientConfig(),
            serverCodecs,
            eurekaClient
    );
    awsBinder = new AwsBinderDelegate(eurekaServerConfig, eurekaClient.getEurekaClientConfig(), registry, applicationInfoManager);
    awsBinder.start();
} else {
    registry = new PeerAwareInstanceRegistryImpl(
            eurekaServerConfig,
            eurekaClient.getEurekaClientConfig(),
            serverCodecs,
            eurekaClient
    );
}

//初始化PeerEurekaNodes,里面有定时维护Eureka集群的业务逻辑
PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
        registry,
        eurekaServerConfig,
        eurekaClient.getEurekaClientConfig(),
        serverCodecs,
        applicationInfoManager
);


//初始化EurekaServer上下文
serverContext = new DefaultEurekaServerContext(
        eurekaServerConfig,
        serverCodecs,
        registry,
        peerEurekaNodes,
        applicationInfoManager
);

EurekaServerContextHolder.initialize(serverContext);

serverContext.initialize();
logger.info("Initialized server context");

//从其他节点中读取注册信息,并开放服务注册
// Copy registry from neighboring eureka node
int registryCount = registry.syncUp();
registry.openForTraffic(applicationInfoManager, registryCount);

// Register all monitoring statistics.
EurekaMonitors.registerAllStats();

}

总结下来,总共如下几点:

1.初始化并设置序列化反序列化工具
2.初始化通信客户端EurekaClient
3.初始化集群通信类PeerAwareInstanceRegistry与PeerEurekaNodes
4.初始化EurekaServer上下文serverContext
5.从其他节点中读取注册信息,并开放服务注册

然后,由于原生的EurekaServer利用Jersey框架初始化restApi,这里还有:
6.载入Jersey,初始化Restful服务api

对于胶水代码,实现了大致同样的但是略微有些区别的功能:
一、 Server 有哪些功能:

提供服务注册功能。
消费者可以获取服务列表。
服务可以续约。
Server 集群之间的数据共享

二、 提供服务注册功能

我们使用 EurekaServer 的时候,需要在启动类上加入 @EnableEurekaServer注解,这个注解肯定就是我们研究的入口。

EnableEurekaServer 类:

/**

  • Annotation to activate Eureka Server related configuration.
  • {@link EurekaServerAutoConfiguration}
  • @author Dave Syer
  • @author Biju Kunjummen

*/

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {

}

EurekaServerAutoConfiguration

@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource(“classpath:/eureka/server.properties”)
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter{

}

EurekaServerInitializerConfiguration 由于实现了SmartLifecycle, 初始化启动start()方法; 额外新创建一个线程初始化initEurekaServerContext() , 发布事件等工作

@Configuration
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
@Override
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// TODO: is this class even needed now?
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) {
				// Help!
				log.error("Could not initialize Eureka servlet context", ex);
			}
		}
	}).start();
}

}

EurekaServerAutoConfiguration 中注入EurekaServerContext

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

在初始化化DefaultEurekaServerContext 类的时候,会初始化initialize()方法,是因为在此方法上面@PostConstruct注解. peerEurekaNodes.start() 中。使用单定时任务线程池,维护eureka节点

@PostConstruct
@Override
public void initialize() {
    logger.info("Initializing ...");
    peerEurekaNodes.start();
    try {
        registry.init(peerEurekaNodes);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    logger.info("Initialized");
}

http://www.niftyadmin.cn/n/5475485.html

相关文章

LangChain - OpenGPTs

文章目录 MessageGraph 消息图认知架构AssistantsRAGChatBot 持久化配置新模型新工具astream_events总结 关键链接: OpenGPT GitHub 存储库YouTube 上的 OpenGPT 演练LangGraph:Python、JS 两个多月前,在 OpenAI 开发日之后,我们…

【引子】C++从介绍到HelloWorld

C从介绍到HelloWorld 一、C的介绍1. 简介2. 应用场景3. C的标准![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e3efb0f207f647729b92c0b5bcd4b330.png)4. C的运行过程 二、Visual Studio的安装1. 什么是Visual Studio2. Visual Studio的安装 三、完成HelloWorld1.…

目标跟踪——行人检测数据集

一、重要性及意义 目标跟踪和行人检测是计算机视觉领域的两个重要任务,它们在许多实际应用中发挥着关键作用。为了推动这两个领域的进步,行人检测数据集扮演着至关重要的角色。以下是行人检测数据集的重要性及意义的详细分析: 行人检测数据…

11.java openCV4.x 入门- Imgcodecs之图像读写

专栏简介 💒个人主页 📰专栏目录 点击上方查看更多内容 📖心灵鸡汤📖我们唯一拥有的就是今天,唯一能把握的也是今天建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫 🧭文…

SQLite 4.9的虚拟表机制(十四)

返回:SQLite—系列文章目录 上一篇:SQLite 4.9的 OS 接口或“VFS”(十三) 下一篇:SQLite—系列文章目录 1. 引言 虚拟表是向打开的 SQLite 数据库连接注册的对象。从SQL语句的角度来看, 虚拟表对象与任何其他…

蓝桥杯 历届真题 杨辉三角形【第十二届】【省赛】【C组】

资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 思路: 由于我第一写没考虑到大数据的原因,直接判断导致只得了40分,下面是我的代码: #…

【C++】继承总结

一、前言 我们众所周知的C三大特性分别为:封装、继承、多态。 封装就是将接口实现统一化,隐藏那些不同的地方,在上层函数调用体现的方式一样,如各种容器的迭代器iterator,尽管底层实现的方式不同,但是在使用…

浅谈Mysql(四)——Mysql知识补充

一、mysql什么时候会锁表 MySQL中的查询语句通常不会锁表,因为查询操作只读取数据而不修改数据。然而,当执行某些特定的查询语句或者在特定情况下,MySQL可能会对表进行锁定以保证数据的一致性和完整性。以下是几种可能导致表锁定的情况&#…