Spring Cloud Eureka(五):Eureka Server 启动流程分析
启用EurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
@EnableEurekaServer 源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}
将配置类 EurekaServerMarkerConfiguration 加入spring 容器。
EurekaServerMarkerConfiguration 的源码
/**
*
* 激活 EurekaServerAutoConfiguration 的开关
*/
@Configuration
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
}
class Marker {
}
}
我们看到只是实例化了一个空类,没有任何实现,从注释中可以看到 EurekaServerMarkerConfiguration 是一个激活 EurekaServerAutoConfiguration 的开关。我们在项目源码的 META-INF/spring.factories中看到
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
真正的配置信息在 EurekaServerAutoConfiguration 中,我们看到 @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class) 只有存在 Marker 实例的时候,才会继续加载配置项,这也就要求必须有 @EnableEurekaServer 注解,才能正常的启动。
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
}
简单的梳理一下 @EnableEurekaServer 的流程为:
EurekaServerAutoConfiguration 源码
在源码中我们可以看到一个很重要的注解 @Import(EurekaServerInitializerConfiguration.class) ,该注解是真正的的启动了服务,下面我们就看一下它都有哪些操作
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
}
1、@Configuration 表明这是一个配置类
2、@Import(EurekaServerInitializerConfiguration.class) 导入启动EurekaServer的bean
3、@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class) 这个是表示只有在spring容器
里面含有Market这个实例的时候,才会加载当前这个Bean(EurekaServerAutoConfiguration ),这个就是控制
是否开启EurekaServer的关键,
4、@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })
加载配置
5、@PropertySource(“classpath:/eureka/server.properties”) 加载配置文件。
EurekaServerInitializerConfiguration 实现了SmartLifecycle.start方法,在spring 初始化的时候,会被调用
@Configuration
@CommonsLog
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
@Autowired
private EurekaServerConfig eurekaServerConfig;
private ServletContext servletContext;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private EurekaServerBootstrap eurekaServerBootstrap;
private boolean running;
private int order = 1;
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public void start() {
// 启动一个线程
new Thread(new Runnable() {
@Override
public void run() {
try {
//初始化EurekaServer,同时启动Eureka Server
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
log.info("Started Eureka Server");
// 发布EurekaServer的注册事件
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
// 设置启动的状态为true
EurekaServerInitializerConfiguration.this.running = true;
// 发布Eureka Start 事件,另外还有其他事件,我们可以根据需要监听这些事件,然后做一些特定的业务需求
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
}
catch (Exception ex) {
log.error("Could not initialize Eureka servlet context", ex);
}
}
}).start();
}
private EurekaServerConfig getEurekaServerConfig() {
return this.eurekaServerConfig;
}
private void publish(ApplicationEvent event) {
this.applicationContext.publishEvent(event);
}
@Override
public void stop() {
this.running = false;
eurekaServerBootstrap.contextDestroyed(this.servletContext);
}
.................省略...............
}
eurekaServerBootstrap是spring cloud定义的类,其代码完全拷贝了Eureka启动类的实现。 这里看到在Eureka启动后,会向外发送EurekaRegistryAvailableEvent 和 EurekaServerStartedEvent 事件,我们可以根据需要订阅这两个事件,做具体的处理操作。
接着我们一下 EurekaServerBootstrap 做了哪些具体的操作,从源码中可以看到方法 contextInitialized(ServletContext context) 进行了环境和上下文的初始化工作,下面我们分别看一下:
EurekaServerBootstrap > contextInitialized
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);
}
}
EurekaServerBootstrap > contextInitialized > initEurekaEnvironment
protected void initEurekaEnvironment() throws Exception {
log.info("Setting the eureka configuration..");
//设置数据中心
String dataCenter = ConfigurationManager.getConfigInstance()
.getString(EUREKA_DATACENTER);
if (dataCenter == null) {
log.info(
"Eureka data center value eureka.datacenter is not set, defaulting to default");
ConfigurationManager.getConfigInstance()
.setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
}
else {
ConfigurationManager.getConfigInstance()
.setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
}
//设置 Eureka 环境
String environment = ConfigurationManager.getConfigInstance()
.getString(EUREKA_ENVIRONMENT);
if (environment == null) {
ConfigurationManager.getConfigInstance()
.setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
log.info(
"Eureka environment value eureka.environment is not set, defaulting to test");
}
else {
ConfigurationManager.getConfigInstance()
.setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, environment);
}
}
EurekaServerBootstrap > contextInitialized > initEurekaEnvironment
protected void initEurekaServerContext() throws Exception {
// For backward compatibility
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
if (isAws(this.applicationInfoManager.getInfo())) {
this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig,
this.eurekaClientConfig, this.registry, this.applicationInfoManager);
this.awsBinder.start();
}
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
// 从邻近的eureka节点复制注册表
int registryCount = this.registry.syncUp();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
// 注册所有监控统计信息
EurekaMonitors.registerAllStats();
}
至此,EurekaServer启动完毕, EurekaServerBootstrap是完全复制了原生EurekaBootstrap的代码, 因为原生的Eureka
是在servlet应用,但是spring cloud的应用是运行在内嵌的Tomcat等WEB服务器里面的,所以就使用EurekaServerBootstrap
来做替换,最终使Eureka能够在spring boot中使用。
Spring Cloud Eureka(五):Eureka Server 启动流程分析的更多相关文章
- 【spring cloud】spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V
spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApp ...
- Spring Cloud 入门 之 Eureka 篇(一)
原文地址:Spring Cloud 入门 之 Eureka 篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Cloud 是一系列框架的有序集合.它利用 Sp ...
- Spring Cloud 系列之 Eureka 实现服务注册与发现
如果你对 Spring Cloud 体系还不是很了解,可以先读一下 Spring Cloud 都有哪些模块 Eureka 是 Netflix 开源的服务注册发现组件,服务发现可以说是微服务架构的核心功 ...
- 基于Spring cloud Ribbon和Eureka实现客户端负载均衡
前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...
- spring cloud config与eureka配合使用
前面两篇介绍了Spring Cloud Config服务端和客户端的简单配置,本篇介绍Spring Cloud Config与Eureka配合使用 前言 默认情况下,配置客户端启动时,都是通过配置属性 ...
- Spring Cloud中,Eureka常见问题总结
Spring Cloud中,Eureka常见问题总结. 1 eureka.environment: 指定环境 参考文档: 1 eureka.datacenter: 指定数据中心 参考文档: 使用配置项 ...
- Spring Cloud(五):Hystrix 监控面板【Finchley 版】
Spring Cloud(五):Hystrix 监控面板[Finchley 版] 发表于 2018-04-16 | 更新于 2018-05-10 | 在上一篇 Hystrix 的介绍中,我们提到 ...
- Spring Cloud Netflix之Euraka Server注册中心
Spring Cloud简介 Spring Cloud是基于Spring Boot的一套实现微服务架构的生态组件.生态组件中包含Spring Cloud NetFlix,Spring Cloud Fe ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
随机推荐
- (五)CXF之添加拦截器
一.需求分析 webService中的拦截器类似于servlet的Filter过滤器.一般用于调用服务前后先调用拦截器的方法. 二.案例 本章案例是基于上一章节的基础上添加拦截器的 2.1 服务端添加 ...
- (一)Redis之简介和windows下安装radis
一.简介 1.1 关于nosql 介绍Redis之前,先了解下NoSQL (Not noly SQL)不仅仅是SQL, 属于非关系型数据库:Redis就属于非关系型数据库, 传统的Mysql ,ora ...
- ubuntu装openssh-client和openssh-server
1. 修改update源 进入/etc/apt/目录,首先用cp命令将sources.list备份成sources.list.bk,然后复制http://www.cnblogs.com/eastson ...
- [NOIP2018模拟赛10.22]咕咕报告
闲扯 这是篇咕咕了的博客 考场上码完暴力后不知道干什么,然后忽然发现这个T1好像有点像一道雅礼集训时讲过的CF题目 Rest In Shades ,当时那道题还想了挺久不过思路比较妙,于是我就也\(y ...
- 关于Vue中,checkBox等组件在赋值后,点击切换页面未及时更新问题
我们经常碰到这样的问题,在v-for循环中,给某些组件(此处以checkBox为例)赋值后,组件并不能正常切换, 这是因为数据层太多,render函数没有自动更新,需手动强制刷新. 解决方法:在切换c ...
- 认识:before和:after伪类
有时候,我们需要大量的重复代码去实现一个非常简单的功能,这不仅浪费时间,而且效率低下,例如: <div class="aa">你好</div><div ...
- FPGA上外挂DDR2&DDR3&MIG IP的使用记录
前言 当需要大容量数据存储及处理的时候,FPGA内部自带的存储资源是远远不够的,所以问题来了,怎么使用外带的DDR3? 首要问题在于DDR3是什么?有没有协议?当然只是需要用Xilinx MIG IP ...
- linux内存管理初学
虚拟内存模型 Linux 内核本身并不运行在虚拟空间中,其使用的是物理寻址模式. 物理内存被分割为界面,一个内存页面的大小由PAGE_SIZE宏决定. 虚拟地址空间的方式使程序员可以将巨大的结构用于连 ...
- nginx增加新模块
以gunzip这个模块为例,讲述一下,在nginx中如何安装新的模块 1.首先查看nginx已经安装了哪些模块. nginx –V 2.发现没有gunzip模块,安装 进入nginx的安装目录中,不是 ...
- 使用SQLAlchemy,以及问题处理
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0014021031294178 ...