EurekaServerAutoConfiguration
2021-05-16 12:30:19 0 举报
AI智能生成
EurekaServer 自动化配置
作者其他创作
大纲/内容
源码
@Configuration 首先当前类是一个配置类
@Import(EurekaServerInitializerConfiguration.class)
源码
核心方法: start()
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
@Autowired<br> private EurekaServerBootstrap eurekaServerBootstrap;
源码
核心方法:public void contextInitialized(ServletContext context)
initEurekaEnvironment();
判断dataCenter 是否是null 如果是null 则给ARCHAIUS_DEPLOYMENT_DATACENTER设置为DEFAULT,否则设置为dataCenter
判断environment 是否是null,如果是null 则给ARCHAIUS_DEPLOYMENT_ENVIRONMENT 设置为DEFAULT否则设置为 TEST
initEurekaServerContext();
先认识一下XStream 类
源码
官方源码解释说明
JsonXStream
JsonXStream extends XStream
官方源码解释说明
XmlXStream
XmlXStream extends XStream
官方源码解释说明
this.applicationInfoManager.getInfo()
ApplicationInfoManager
源码
我们可以用来干什么呢?
我们可以在EurekaServer 中
pom 中添加web 的依赖
写一个Controller 方法
源码
我们可以看到 我们可以通过它获取服务的配置对象,以及服务的详细信息对象,以及设置服务的状态,添加一个监听器等等
EurekaServerContextHolder.initialize(this.serverContext);
方法源码
源码注释说明
EurekaServerContextHolder.initialize(this.serverContext);
源码
// Copy registry from neighboring eureka node<br> int registryCount = this.registry.syncUp();
说明: 从相邻的eureka节点复制注册表
从 syncUp() 方法的代码中可以知道是30s一次
方法代码
源码
源码注释
这个类就是EurekaServer的启动引导类
start() 方法中用到了 servletContext
这个值是在什么时候被设置进来的?
当 项目启动,IOC 容器初始化的时候,会调用ServletContextAwareProcessor 类的:public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 方法
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
根据源码注释可知,该注解的作用是往IOC 容器中创建一个Marker bean 用来标识 EurekaServerAutoConfiguration 配置是否已经被激活,也就是说如果IOC 容器中存在这个bean 那么该配置就已经被加载激活过,否则则没有。
@EnableConfigurationProperties({ EurekaDashboardProperties.class,<br> InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
@Autowired<br> private ApplicationInfoManager applicationInfoManager;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired<br> private EurekaServerConfig eurekaServerConfig;
实例化方法
@Configuration<br> protected static class EurekaServerConfigBeanConfiguration {<br> @Bean<br> @ConditionalOnMissingBean<br> public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {<br> EurekaServerConfigBean server = new EurekaServerConfigBean();<br> if (clientConfig.shouldRegisterWithEureka()) {<br> // Set a sensible default if we are supposed to replicate<br> server.setRegistrySyncRetries(5);<br> }<br> return server;<br> }<br> }
@Autowired<br> private EurekaClientConfig eurekaClientConfig;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired<br> private EurekaClient eurekaClient;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired<br> private InstanceRegistryProperties instanceRegistryProperties;
实例化
@EnableConfigurationProperties({ EurekaDashboardProperties.class,<br> InstanceRegistryProperties.class })
InstanceRegistryProperties.class
源码
@ConfigurationProperties
源码
印象笔记:@ConfigurationProperties 注解使用姿势,这一篇就够了
@EnableConfigurationProperties
源码
@Import(EnableConfigurationPropertiesImportSelector.class)
源码
这个注解 可以接收一个vale 数组 并且把该数组的 class 注册进IOC 容器
那我们分析一下这个注解是怎么起作用的
首先是系统启动加载了:@EnableAutoConfiguration
源码
@EnableAutoConfiguration @Import 了EnableAutoConfigurationImportSelector.class
EnableAutoConfigurationImportSelector 类的 selectImports 会获取到:ConfigurationPropertiesAutoConfiguration 这个类
源码
@Import(EnableConfigurationPropertiesImportSelector.class)
源码
核心
org.springframework.boot.context.properties.EnableConfigurationPropertiesImportSelector.ConfigurationPropertiesBeanRegistrar#registerBeanDefinitions
源码
把注解value 进行注入
@Bean<br> public HasFeatures eurekaServerFeature()
核心代码
@Bean<br> public HasFeatures eurekaServerFeature() {<br> return HasFeatures.namedFeature("Eureka Server",<br> EurekaServerAutoConfiguration.class);<br> }
就是创建了一个 名称和EurekaServerAutoConfiguration key value 对应关系的一个对象
我们可以自己 添加映射关系
EurekaClientAutoConfiguration 配置类 里面也有这么类型的一个对象
@Bean<br> public HasFeatures eurekaFeature() {<br> return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);<br> }
HasFeatures
源码
@Configuration<br> protected static class EurekaServerConfigBeanConfiguration
核心代码
@Configuration<br> protected static class EurekaServerConfigBeanConfiguration {<br> @Bean<br> @ConditionalOnMissingBean<br> public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {<br> EurekaServerConfigBean server = new EurekaServerConfigBean();<br> if (clientConfig.shouldRegisterWithEureka()) {<br> // Set a sensible default if we are supposed to replicate<br> server.setRegistrySyncRetries(5);<br> }<br> return server;<br> }<br> }
就是创建了EurekaServerConfig 的实例对象
@Bean<br> @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)<br> public EurekaController eurekaController()
这个实际上就是Eureka 自带的一个Controller 类,对我提供暴露了一下接口
EurekaController
源码
@Bean<br> public ServerCodecs serverCodecs()
创建了一个编码解码器
@Bean<br> public PeerAwareInstanceRegistry peerAwareInstanceRegistry
初始化集群注册表
@Bean<br> @ConditionalOnMissingBean<br> public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,<br> ServerCodecs serverCodecs)
初始化集群节点集合
@Bean<br> public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,<br> PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes)
基于EurekaServer配置 注册表 集群节点集合 以及服务初始化EurekaServer上下文
@Bean<br> public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,<br> EurekaServerContext serverContext)
核心方法
@Bean<br> public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,<br> EurekaServerContext serverContext) {<br> return new EurekaServerBootstrap(this.applicationInfoManager,<br> this.eurekaClientConfig, this.eurekaServerConfig, registry,<br> serverContext);<br> }
源码
这个是 EurekaServer 启动初始化的入口
流程
我们EurekaServerAutoConfiguration 配置类中的Bean 全部初始化之后
EurekaServerAutoConfiguration 的注解 @Import(EurekaServerInitializerConfiguration.class) 实现了SmartLifecycle 实现了这个接口的 会在项目启动后,调用start() 方法
start() 方法中调用了eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
初始化EurekaServer
核心代码
public void contextInitialized(ServletContext context) {<br> try {<br> initEurekaEnvironment();<br> initEurekaServerContext();<br><br> context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);<br> }<br> catch (Throwable e) {<br> log.error("Cannot bootstrap eureka server :", e);<br> throw new RuntimeException("Cannot bootstrap eureka server :", e);<br> }<br> }
initEurekaEnvironment();
initEurekaServerContext();
int registryCount = this.registry.syncUp();
从相邻的eureka节点复制注册表
源码
Applications apps = eurekaClient.getApplications();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
1. 修改eureka状态为up<br>2. 开启一个定时任务,清理60s没有 续约实例
@Override<br> public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {<br> // Renewals happen every 30 seconds and for a minute it should be a factor of 2.<br> this.expectedNumberOfRenewsPerMin = count * 2;<br> this.numberOfRenewsPerMinThreshold =<br> (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());<br> logger.info("Got " + count + " instances from neighboring DS node");<br> logger.info("Renew threshold is: " + numberOfRenewsPerMinThreshold);<br> this.startupTime = System.currentTimeMillis();<br> if (count > 0) {<br> this.peerInstancesTransferEmptyOnStartup = false;<br> }<br> DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();<br> boolean isAws = Name.Amazon == selfName;<br> if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) {<br> logger.info("Priming AWS connections for all replicas..");<br> primeAwsReplicas(applicationInfoManager);<br> }<br> logger.info("Changing status to UP");<br> applicationInfoManager.setInstanceStatus(InstanceStatus.UP);<br> super.postInit();<br> }
核心方法
primeAwsReplicas(applicationInfoManager);
super.postInit();
protected void postInit() {<br> renewsLastMin.start();<br> if (evictionTaskRef.get() != null) {<br> evictionTaskRef.get().cancel();<br> }<br> evictionTaskRef.set(new EvictionTask());<br> evictionTimer.schedule(evictionTaskRef.get(),<br> serverConfig.getEvictionIntervalTimerInMs(),<br> serverConfig.getEvictionIntervalTimerInMs());<br> }
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()))
发布注册中心启动事件
EurekaServerInitializerConfiguration.this.running = true
标记EurekaServer 处于运行中
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
注册中心服务启动事件
@Bean<br> public FilterRegistrationBean jerseyFilterRegistration(<br> javax.ws.rs.core.Application eurekaJerseyApp)
实现过滤器的一种方式
实现过滤器有两种方式
通过FilterRegistrationBean实例注册
通过@WebFilter注解生效
第一种相对于第二种的优点是,可以自己设置过滤器之间的优先级
@Bean<br> public javax.ws.rs.core.Application jerseyApplication(Environment environment,<br> ResourceLoader resourceLoader)
@Bean<br> public FilterRegistrationBean traceFilterRegistration(<br> @Qualifier("webRequestLoggingFilter") Filter filter)
EurekaClientAutoConfiguration 是 springboot 启动的时候 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports 方法加载的
源码
核心代码
configurations = sort(configurations, autoConfigurationMetadata);
排序之后 我们发现 是先加载 EurekaClientAutoConfiguration 然后再加载EurekaServerAutoConfiguration
EurekaServerAutoConfiguration 配置类的很多@Autowired 注入的对象都是 在 EurekaClientAutoConfiguration 中实例化的
1
@Autowired<br> private ApplicationInfoManager applicationInfoManager;
@Autowired<br> private EurekaClient eurekaClient;
这两个是
2
@Autowired<br> private EurekaClientConfig eurekaClientConfig;
@Bean<br> @ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)<br> public EurekaClientConfigBean eurekaClientConfigBean() {<br> EurekaClientConfigBean client = new EurekaClientConfigBean();<br> if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {<br> // We don't register during bootstrap by default, but there will be another<br> // chance later.<br> client.setRegisterWithEureka(false);<br> }<br> return client;<br> }
EurekaClientConfigBean
我们可以通过打断点发现 这个return 的client 和EurekaServerAutoConfiguration 注入的对象是同一个
0 条评论
下一页