Spring Cloud之Eureka Server启动流程分析

启动流程分析图如下:

在这里插入图片描述

  1. Eureka Server启动类:
/**
 1. 启动一个服务注册中心,只需要一个注解@EnableEurekaServer
 */
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
  1. 注解@EnableEurekaServer源码:我们看到该注解导入了EurekaServerMarkerConfiguration类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {

}
  1. EurekaServerMarkerConfiguration类作为配置文件,引入Marker类,激活 EurekaServerAutoConfiguration
/**
 *  激活 EurekaServerAutoConfiguration 的开关 
 * Responsible for adding in a marker bean to activate
 * {@link EurekaServerAutoConfiguration}.
 *
 * @author Biju Kunjummen
 */
@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

进入EurekaServerMarkerConfiguration,点击idea左上角的圆标,即可看到:
在这里插入图片描述

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

}

在源码中我们可以看到一个很重要的注解 @Import(EurekaServerInitializerConfiguration.class) ,该注解是真正的的启动了服务

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”) 加载配置文件。

  1. EurekaServerInitializerConfiguration源码核心代码如下:
@Configuration
public class EurekaServerInitializerConfiguration
		implements ServletContextAware, SmartLifecycle, Ordered {
	@Autowired
	private EurekaServerConfig eurekaServerConfig;

	private ServletContext servletContext;

	@Autowired
	private ApplicationContext applicationContext;

	@Autowired
	private EurekaServerBootstrap eurekaServerBootstrap;

	@Override
	public void start() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					//1,初始化eurekaServer,同时启动eurekaServer
					eurekaServerBootstrap.contextInitialized(
							EurekaServerInitializerConfiguration.this.servletContext);
					log.info("Started Eureka Server");
					//2,发布Eureka注册事件
					publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
					//3,设置EurekaServer的状态为true
					EurekaServerInitializerConfiguration.this.running = true;
					//4,发布EurekaServer启动事件
					publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
				}
				catch (Exception ex) {
					log.error("Could not initialize Eureka servlet context", ex);
				}
			}
		}).start();
	}
}

该类继承了SmartLifecycle,重写了它的start()方法,开启一个线程做了一些初始化的工作。

  1. EurekaServerBootstrap类做的一些启动事件:
public void contextInitialized(ServletContext context) {
		try {
			//1,初始化Eureka执行环境
			initEurekaEnvironment();
			//2,初始化Eureka上下文
			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);
		}
	}
  1. EurekaServerBootstrap -> contextInitialized() -> initEurekaEnvironment(),初始化Eureka环境
protected void initEurekaEnvironment() throws Exception {
		log.info("Setting the eureka configuration..");
		//1,设置数据中心,启动时获取的是null,所以设置为默认值
		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);
		}
		//2,设置环境值,启动时也是null,设置为默认值
		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);
		}
	}
  1. EurekaServerBootstrap -> contextInitialized() -> initEurekaServerContext(),初始化Eureka上下文
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");
		//1,从邻近的eureka结点复制注册表
		int registryCount = this.registry.syncUp();
		this.registry.openForTraffic(this.applicationInfoManager, registryCount);

		// 2,注册所有监控统计信息
		EurekaMonitors.registerAllStats();
	}

总结:

至此,EurekaServer启动完毕, EurekaServerBootstrap是完全复制了原生EurekaBootstrap的代码, 因为原生的Eureka是在servlet应用,但是spring cloud的应用是运行在内嵌的Tomcat的WEB服务器里面的,所以就使用EurekaServerBootstrap来做替换,最终使Eureka能够在spring boot中使用。

参考博客:https://blog.csdn.net/u010647035/article/details/83048894

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值