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")publicclassEurekaServerAutoConfigurationextendsWebMvcConfigurerAdapter {...
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() {
returnHasFeatures.namedFeature("Eureka Server",
EurekaServerAutoConfiguration.class);
}
2) 在静态内部类中有条件的实例化了eureka服务端配置,配置类为 EurekaServerConfig;
@Configuration
protectedstaticclass EurekaServerConfigBeanConfiguration {
@Bean
@ConditionalOnMissingBean
public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
EurekaServerConfigBean server =new EurekaServerConfigBean();
if (clientConfig.shouldRegisterWithEureka()) {
// Set a sensible default if we are supposed to replicateserver.setRegistrySyncRetries(5);
}
return server;
}
}
3)实例化了进入eureka控制面板的Controller类:EurekaController:用于展示eureka面板
@Bean
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing =true)
public EurekaController eurekaController() {
returnnewEurekaController(this.applicationInfoManager);
}
4)eureka服务的Context维护
@Bean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
returnnewDefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs,
registry, peerEurekaNodes, this.applicationInfoManager);
}
5)实例化了eureka多个服务维持节点同步的bean;初始化注册表
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
ServerCodecs serverCodecs) {
this.eurekaClient.getApplications();// force initializationreturnnewInstanceRegistry(this.eurekaServerConfig,this.eurekaClientConfig,
serverCodecs, this.eurekaClient,
this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(),
this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}
6)管理每个eureka服务节点的生命周期
@Bean
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
ServerCodecs serverCodecs) {
returnnewPeerEurekaNodes(registry,this.eurekaServerConfig,
this.eurekaClientConfig, serverCodecs,this.applicationInfoManager);
}
7)通过tomcat维护管理eureka生命周期
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
returnnewEurekaServerBootstrap(this.applicationInfoManager,
this.eurekaClientConfig,this.eurekaServerConfig, registry,
serverContext);
}
1.3 Eureka服务的启动
1)在EurekaServerBootstrap类中我们看到了初始化方法:
publicvoid contextInitialized(ServletContext context) {
try {
//看源码可知这里主要初始化服务环境,配置信息; initEurekaEnvironment();
//初始化了eureka服务端的上下文 initEurekaServerContext();
context.setAttribute(EurekaServerContext.class.getName(),this.serverContext);
}
catch (Throwable e) {
log.error("Cannot bootstrap eureka server :", e);
thrownewRuntimeException("Cannot bootstrap eureka server :", e);
}
}
在这个方法中我们看到了初始化eureka-server环境配置及eureka-server上下文的操作,那么这个方法应该在一个地方有调用,通过查找调用发现:
@Configuration
@CommonsLogpublicclass EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
@Override
publicvoid start() {
newThread(new Runnable() {
@Override
publicvoid 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
publicvoid 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(newEurekaRegistryAvailableEvent(getEurekaServerConfig()));
3)发布Eureka Start事件的pubilsh
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
那么在启动eureka服务有哪些操作呢?深入跟进下源码.
protectedvoidinitEurekaServerContext()throws Exception {
// For backward compatibilityJsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
XStream.PRIORITY_VERY_HIGH);
if(isAws(this.applicationInfoManager.getInfo())) {
this.awsBinder =newAwsBinderDelegate(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
//服务同步
intregistryCount =this.registry.syncUp();
//服务剔除
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
// Register all monitoring statistics. EurekaMonitors.registerAllStats();
}
在初始化eureka服务端initEurekaServerContext()方法中,主要做了初始化server上下文,同步了其他节点的信息,启动了剔除不可用eureka客户端的定时任务;