启用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 的流程为:

import
扫描到
条件判断
加载具体配置信息
EnableEurekaServer
EurekaServerMarkerConfiguration
EurekaServerAutoConfiguration
ConditionalOnBean
EurekaServerAutoConfiguration

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 启动流程分析的更多相关文章

  1. 【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 ...

  2. Spring Cloud 入门 之 Eureka 篇(一)

    原文地址:Spring Cloud 入门 之 Eureka 篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Cloud 是一系列框架的有序集合.它利用 Sp ...

  3. Spring Cloud 系列之 Eureka 实现服务注册与发现

    如果你对 Spring Cloud 体系还不是很了解,可以先读一下 Spring Cloud 都有哪些模块 Eureka 是 Netflix 开源的服务注册发现组件,服务发现可以说是微服务架构的核心功 ...

  4. 基于Spring cloud Ribbon和Eureka实现客户端负载均衡

    前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...

  5. spring cloud config与eureka配合使用

    前面两篇介绍了Spring Cloud Config服务端和客户端的简单配置,本篇介绍Spring Cloud Config与Eureka配合使用 前言 默认情况下,配置客户端启动时,都是通过配置属性 ...

  6. Spring Cloud中,Eureka常见问题总结

    Spring Cloud中,Eureka常见问题总结. 1 eureka.environment: 指定环境 参考文档: 1 eureka.datacenter: 指定数据中心 参考文档: 使用配置项 ...

  7. Spring Cloud(五):Hystrix 监控面板【Finchley 版】

    Spring Cloud(五):Hystrix 监控面板[Finchley 版]  发表于 2018-04-16 |  更新于 2018-05-10 |  在上一篇 Hystrix 的介绍中,我们提到 ...

  8. Spring Cloud Netflix之Euraka Server注册中心

    Spring Cloud简介 Spring Cloud是基于Spring Boot的一套实现微服务架构的生态组件.生态组件中包含Spring Cloud NetFlix,Spring Cloud Fe ...

  9. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

随机推荐

  1. Java InterpolationSearch

    Java InterpolationSearch /** * <html> * <body> * <P> Copyright 1994-2018 JasonInte ...

  2. Window环境下使用多个Git账号(github,gitee,gitlab,gogs等)

    个人电脑之前已经设置好github账号了,公司用的是gitlab私服,一直互不干扰,因为用的是不同的电脑,也就懒得配置git多账户环境.最近看了一下多年空空如也的码云,想着怎么的也会用到gitee来托 ...

  3. solr-jd

    springMVC.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...

  4. DataGridView绑定数据、删除数据

    定义学生类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...

  5. Python练习_函数进阶_day10

    1. 1.作业 1,写函数,接收n个数字,求这些参数数字的和.(动态传参) 2,读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? a=10 b=20 def test5(a,b): p ...

  6. 前端编译原理 简述-jison

    最近几年的项目技术难点都和编译原理,抽象语法树,代码编辑器 有关系.现在时间有点空,先从基础了解起来,让有些交互和提示能够更智能些. 编译原理-Parser    编译原理 其实就是 让计算机懂的 “ ...

  7. js中拼接html代码时onclick参数问题

    一.如果是int类型.可以直接传参 二.如果是字符串类型.需要加上引号 1.使用转义符号\转义引号: (\''+strings+'\') 2.使用"  .比如: ("'+strin ...

  8. flask的多个url对应同一个视图函数

    # -*- coding: utf-8 -*- from flask import Flask app = Flask(__name__) @app.route('/') def index(): r ...

  9. Selenium(十)测试用例错误处理、日志接口、多用户测试

    1.一般的错误类型 2.查看错误提示,是一个div,以id为例找到该元素 3.修改测试用例 def checkResult(driver,err_id): try: err = driver.find ...

  10. springBoot maven项目打成jar包

    springBoot项目打包springBoot项目打包最常用且最简单的方式是用springBoot的打包plugin <plugin> <groupId>org.spring ...