Eureka運行流程
流程描述
1,啟動過程分析
1.1 @EnableEurekaServer注解,來標記啟動注冊中心功能
@EnableDiscoveryClient @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(EurekaServerMarkerConfiguration.class) public @interface EnableEurekaServer { }
源碼中有2個重要的操作
1,使用注解@EnableDiscoveryClent,開啟SpringCloud服務發現客戶端的注解,由於SpringCloud在服務發現組件上不止支持Eureka,還支持例如Alibaba的Dubbo等。
2,Import(EurekaServerMarkerConfiguration.Class),導入配置類,此配置類還實例化了一個Marker的bean。
看下自動配置EurekaServerAutoConfiguration 源碼
@Configuration @Import(EurekaServerInitializerConfiguration.class) @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class) @EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class }) @PropertySource("classpath:/eureka/server.properties") public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {...
1)自動配置類實例化的前提是上下文中存在EurekaServerMarkerConfiguration.Marker這個bean
2)通過@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })導入了兩個配置類
EurekaDashboardProperties用於控制eureka面板的啟動及打開路徑。
InstanceRegistryProperties 設置續約數量和通信數量
3)使用@Import導入配置類EurekaServerInitializerConfiguration.class
4)PropertySource控制字符集編碼的;
1.2 配置類EurekaServerAutoConfiguration
1)實例化bean
@Bean public HasFeatures eurekaServerFeature() { return HasFeatures.namedFeature("Eureka Server", EurekaServerAutoConfiguration.class); }
2) 在靜態內部類中有條件的實例化了eureka服務端配置,配置類為 EurekaServerConfig;

@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; } }
3)實例化了進入eureka控制面板的Controller類:EurekaController:用於展示eureka面板

@Bean @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true) public EurekaController eurekaController() { return new EurekaController(this.applicationInfoManager); }
4)eureka服務的Context維護
@Bean public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs, PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) { return new DefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs, registry, peerEurekaNodes, this.applicationInfoManager); }
5)實例化了eureka多個服務維持節點同步的bean;初始化注冊表
@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()); }
6)管理每個eureka服務節點的生命周期
@Bean @ConditionalOnMissingBean public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry, ServerCodecs serverCodecs) { return new PeerEurekaNodes(registry, this.eurekaServerConfig, this.eurekaClientConfig, serverCodecs, this.applicationInfoManager); }
7)通過tomcat維護管理eureka生命周期
@Bean public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) { return new EurekaServerBootstrap(this.applicationInfoManager, this.eurekaClientConfig, this.eurekaServerConfig, registry, serverContext); }
1.3 Eureka服務的啟動
1)在EurekaServerBootstrap類中我們看到了初始化方法:
public void contextInitialized(ServletContext context) { try { //看源碼可知這里主要初始化服務環境,配置信息; initEurekaEnvironment(); //初始化了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); } }
在這個方法中我們看到了初始化eureka-server環境配置及eureka-server上下文的操作,那么這個方法應該在一個地方有調用,通過查找調用發現:
@Configuration @CommonsLog 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(); } @Override public void stop() { this.running = false; eurekaServerBootstrap.contextDestroyed(this.servletContext); } ..... 部分代碼省略..... }
EurekaServerInitializerConfiguration中操作如下:
1)start()初始化,
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext); log.info("Started Eureka Server");
2)發布EurekaServer的注冊事件pubilsh
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
3)發布Eureka Start事件的pubilsh
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
那么在啟動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"); // Copy registry from neighboring eureka node
//服務同步 int registryCount = this.registry.syncUp();
//服務剔除 this.registry.openForTraffic(this.applicationInfoManager, registryCount); // Register all monitoring statistics. EurekaMonitors.registerAllStats(); }
在初始化eureka服務端initEurekaServerContext()方法中,主要做了初始化server上下文,同步了其他節點的信息,啟動了剔除不可用eureka客戶端的定時任務;