[Spring Cloud Eureka]
本次spring-cloud-starter-eureka-server源码的版本为1.3.0
spring-cloud-starter-eureka-server 目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 ├── pom.xml └── src ├── main │ ├── java │ │ └── org │ │ └── springframework │ │ └── cloud │ │ └── netflix │ │ └── eureka │ │ └── server │ │ ├── CloudJacksonJson.java │ │ ├── EnableEurekaServer.java │ │ ├── EurekaController.java │ │ ├── EurekaDashboardProperties.java │ │ ├── EurekaServerAutoConfiguration.java │ │ ├── EurekaServerBootstrap.java │ │ ├── EurekaServerConfigBean.java │ │ ├── EurekaServerInitializerConfiguration.java │ │ ├── EurekaServerMarkerConfiguration.java │ │ ├── InstanceRegistry.java │ │ ├── InstanceRegistryProperties.java │ │ └── event │ │ ├── EurekaInstanceCanceledEvent.java │ │ ├── EurekaInstanceRegisteredEvent.java │ │ ├── EurekaInstanceRenewedEvent.java │ │ ├── EurekaRegistryAvailableEvent.java │ │ └── EurekaServerStartedEvent.java │ ├── resources │ │ ├── META-INF │ │ │ └── spring.factories │ │ ├── eureka │ │ │ └── server.properties │ │ ├── static │ │ │ └── eureka │ │ │ ├── fonts │ │ │ │ ├── montserrat-webfont.eot │ │ │ │ ├── montserrat-webfont.svg │ │ │ │ ├── montserrat-webfont.ttf │ │ │ │ ├── montserrat-webfont.woff │ │ │ │ ├── varela_round-webfont.eot │ │ │ │ ├── varela_round-webfont.svg │ │ │ │ ├── varela_round-webfont.ttf │ │ │ │ └── varela_round-webfont.woff │ │ │ └── images │ │ │ ├── 404 -icon.png │ │ │ ├── homepage-bg.jpg │ │ │ ├── platform-bg.png │ │ │ ├── platform-spring-xd.png │ │ │ ├── spring-logo-eureka-mobile.png │ │ │ └── spring-logo-eureka.png │ │ └── templates │ │ └── eureka │ │ ├── header.ftl │ │ ├── lastn.ftl │ │ ├── navbar.ftl │ │ └── status.ftl │ └── wro │ ├── header.less │ ├── main.less │ ├── responsive.less │ ├── typography.less │ ├── wro.properties │ └── wro.xml └── test ├── java │ └── org │ └── springframework │ └── cloud │ └── netflix │ └── eureka │ └── server │ ├── ApplicationContextTests.java │ ├── ApplicationDashboardDisabledTests.java │ ├── ApplicationDashboardPathTests.java │ ├── ApplicationServletPathTests.java │ ├── ApplicationTests.java │ ├── EurekaControllerReplicasTests.java │ ├── EurekaControllerTests.java │ ├── EurekaCustomPeerNodesTests.java │ └── InstanceRegistryTests.java └── resources └── application.properties
spring-boot-starter-eureka-server启动分析 在META-INF目录下有个spring.factories文件
1 2 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
spring-boot在启动过程中通过加载、解析spring.factories文件中的信息,对一些bean进行自动装配,在这里我们就不关注了spring-boot 自动配置
我们可以看到EurekaServerAutoConfiguration类由spring ioc来装配, 加载了EurekaServerInitializerConfiguration类 并且把eureka dashboard、register等配置属性注入到EurekaDashboardProperties和InstanceRegistryProperties类中
1 2 3 4 5 6 7 8 9 @Configuration @Import (EurekaServerInitializerConfiguration.class ) @ConditionalOnBean (EurekaServerMarkerConfiguration .Marker .class ) @EnableConfigurationProperties ( { EurekaDashboardProperties.class , InstanceRegistryProperties .class }) @PropertySource("classpath:/eureka/server.properties") public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter { ...... }
EurekaServerInitializerConfiguration 实现了SmartLifecycle接口的start方法,会在所有spring bean都初始化完成后调用该方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Configuration @CommonsLog public class EurekaServerInitializerConfiguration implements ServletContextAware , SmartLifecycle , Ordered { ... @Override public void start () { new Thread(new Runnable() { @Override public void run () { try { 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) { log.error("Could not initialize Eureka servlet context" , ex); } } }).start(); } @Bean public EurekaServerBootstrap eurekaServerBootstrap (PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) { return new EurekaServerBootstrap(this .applicationInfoManager, this .eurekaClientConfig, this .eurekaServerConfig, registry, serverContext); } ... }
Eureka Config wiki: https://github.com/Netflix/eureka/wiki/Configuring-Eureka
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 @CommonsLog public class EurekaServerBootstrap { .... 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); } } 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); } 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); } } protected void initEurekaServerContext () throws Exception { 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" ); int registryCount = this .registry.syncUp(); this .registry.openForTraffic(this .applicationInfoManager, registryCount); EurekaMonitors.registerAllStats(); } ... }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Override public int syncUp () { int count = 0 ; 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; }
事件处理 Spring Cloud Netflix Eureka Server中提供了5个事件通知类
EurekaInstanceCanceledEvent 服务下线事件
EurekaInstanceRegisteredEvent 服务注册事件
EurekaInstanceRenewedEvent 服务续约事件
EurekaRegistryAvailableEvent Eureka注册中心启动事件
EurekaServerStartedEvent Eureka Server启动事件
我可以实现listen去处理这些动作