Eureka Server源码分析(1)从@EnableEurekaServer注解开始分析

Eureka启动源码分析

我们从@EnableEurekaServer注解开始分析

1.Eureka Server启动分析

1.1找到@EnableEurekaServer的实现类 EurekaServerAutoConfiguration
1.2分析EurekaServerInitializerConfiguration(eureka配置的加载类)

@Configuration
//EurekaServer配置
@Import(EurekaServerInitializerConfiguration.class)
//启动配置。
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
//加载EurekaDashboardProperties和InstanceRegistryProperties配置
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
		InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
	/**
	 * 省略大部分代码,仅抽取一些关键的代码片段
	 */

	//EurekaServerConfigBean初始化,设置Eureka相互注册 
	@Configuration
	protected static class EurekaServerConfigBeanConfiguration {
		@Bean
		@ConditionalOnMissingBean
		public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
			EurekaServerConfigBean server = new EurekaServerConfigBean();
			if (clientConfig.shouldRegisterWithEureka()) {
				// Set a sensible default if we are supposed to replicate
				server.setRegistrySyncRetries(5);
			}
			return server;
		}
	}
	//初始化EurekaController,提供访问接口 
	@Bean
	@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
	public EurekaController eurekaController() {
		return new EurekaController(this.applicationInfoManager);
	}
	

	//省略编码和解码,json解析
	
	//实例化了eureka多个服务维持节点同步的bean(PeerAwareInstanceRegistry );以及每个eureka服务节点的生命周期管理(PeerEurekaNodes );
	@Bean
	public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
			ServerCodecs serverCodecs) {
		this.eurekaClient.getApplications(); // force initialization
		return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
				serverCodecs, this.eurekaClient,
				this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(),
				this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
	}

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

	static class RefreshablePeerEurekaNodes extends PeerEurekaNodes
			implements ApplicationListener<EnvironmentChangeEvent> {

		public RefreshablePeerEurekaNodes(
				final PeerAwareInstanceRegistry registry,
				final EurekaServerConfig serverConfig,
				final EurekaClientConfig clientConfig, 
				final ServerCodecs serverCodecs,
				final ApplicationInfoManager applicationInfoManager) {
			super(registry, serverConfig, clientConfig, serverCodecs, applicationInfoManager);
		}

		@Override
		public void onApplicationEvent(final EnvironmentChangeEvent event) {
			if (shouldUpdate(event.getKeys())) {
				updatePeerEurekaNodes(resolvePeerUrls());
			}
		}
		
		/*
		 * 检查配置是否发生变化,
		 */
		protected boolean shouldUpdate(final Set<String> changedKeys) {
			assert changedKeys != null;
			
			// if eureka.client.use-dns-for-fetching-service-urls is true, then
			// service-url will not be fetched from environment.
			if (clientConfig.shouldUseDnsForFetchingServiceUrls()) {
				return false;
			}
			
			if (changedKeys.contains("eureka.client.region")) {
				return true;
			}
			
			for (final String key : changedKeys) {
				// property keys are not expected to be null.
				if (key.startsWith("eureka.client.service-url.") ||
					key.startsWith("eureka.client.availability-zones.")) {
					return true;
				}
			}
			
			return false;
		}
	}

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

	// EurekaServer的引导程序(提供其他类调用,去实现),通过tomcat管理eureka的生命周期;
	@Bean
	public EurekaServerBootstrap eurekaServerBootstrap(){}


	//省略Jersey,类似于springmvc的框架,restFul风格
}

2. EurekaServerInitializerConfiguration(eureka配置文件的加载逻辑)

2.1启动一个线程去读取配置文件,主要初始化服务环境,配置信息;初始化了eureka服务端的上下文,并发布通知eureka注册成功事件和eureka启动事件。初始化EurekaRegistryAvailableEvent和EurekaServerStartedEvent

@Override
public void start() {
new Thread(new Runnable() {
	@Override
	public void run() {
		try {
			
			
			//1.上下文初始化
			eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
			log.info("Started Eureka Server");
			//2.广播注册事件
			publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
			EurekaServerInitializerConfiguration.this.running = true;
			//3.广播EurekaServer启动事件
			publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
		}
		catch (Exception ex) {
			// Help!
			log.error("Could not initialize Eureka servlet context", ex);
		}
	}
}).start();
}

//1.上下文初始化
public void contextInitialized(ServletContext context) {
		try {
			//1.1初始化环境配置文件
			initEurekaEnvironment();
			//这个方法中有一个syncUp()函数用于注册peer实例
			//1.2初始化EurekaServer上下文
			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.2初始化EurekaServer上下文
	protected void initEurekaServerContext() throws Exception {
		//1.2.1省略Json流和XMl流解析器的初始化
		
		//1.2.2省略aws事件
		
		//1.2.3真正初始化server context
		EurekaServerContextHolder.initialize(this.serverContext);

		log.info("Initialized server context");

		//1.2.4 从相邻的Eureka节点复制注册表(重要)
		int registryCount = this.registry.syncUp();
		//1.2.5 设置一些参数和打印日志,设置从其他Server中获取的服务状态为up,
		//开启一些定时任务。(重要)
		this.registry.openForTraffic(this.applicationInfoManager, registryCount);

		//1.2.6 监控jmx支持的注册表.
		EurekaMonitors.registerAllStats();
	}
	//1.2.4 从相邻的Eureka节点复制注册表(重要),有过期时间的就不修改,没有则创建
	@Override
    public int syncUp() {
        //计算获取的注册实例数目
        int count = 0;
		//1.2.4.1将注册实例注册
        for (int i = 0; ((i < serverConfig.getRegistrySyncRetries()) && (count == 0)); i++) {
            if (i > 0) {
                try {
                    Thread.sleep(serverConfig.getRegistrySyncRetryWaitMs());
                } catch (InterruptedException e) {
                    logger.warn("Interrupted during registry transfer..");
                    break;
                }
            }
            Applications apps = eurekaClient.getApplications();
            for (Application app : apps.getRegisteredApplications()) {
                for (InstanceInfo instance : app.getInstances()) {
                    try {
                        if (isRegisterable(instance)) {
                            register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
                            count++;
                        }
                    } catch (Throwable t) {
                        logger.error("During DS init copy", t);
                    }
                }
            }
        }
        return count;
    }
    //1.2.5 开启的定时任务
    protected void postInit() {
        renewsLastMin.start();
        if (evictionTaskRef.get() != null) {
            evictionTaskRef.get().cancel();
        }
        evictionTaskRef.set(new EvictionTask());
        evictionTimer.schedule(evictionTaskRef.get(),
                serverConfig.getEvictionIntervalTimerInMs(),
                serverConfig.getEvictionIntervalTimerInMs());
    }

介绍一下EurekaServerAutoConfiguration类中的Bean的启动顺序

  1. eurekaServerConfig
  2. jerseyApplication
  3. jerseyFilterRegistration
  4. traceFilterRegistration
  5. peerAwareInstanceRegistry
  6. peerEurekaNodes
  7. RefreshablePeerEurekaNodes
  8. eurekaServerContext
  9. eurekaServerBootstrap
  10. EurekaController
  11. EurekaServerInitializerConfiguration
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值