EurekaServerAutoConfiguration
2021-05-16 12:30:19 0 举报
AI智能生成
EurekaServer 自动化配置
作者其他创作
大纲/内容
源码
@Configuration 首先当前类是一个配置类
@Import(EurekaServerInitializerConfiguration.class)
源码
核心方法: start()
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
@Autowired
private EurekaServerBootstrap eurekaServerBootstrap;
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
int registryCount = this.registry.syncUp();
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,
InstanceRegistryProperties.class })
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
@Autowired
private ApplicationInfoManager applicationInfoManager;
private ApplicationInfoManager applicationInfoManager;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired
private EurekaServerConfig eurekaServerConfig;
private EurekaServerConfig 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;
}
}
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;
}
}
@Autowired
private EurekaClientConfig eurekaClientConfig;
private EurekaClientConfig eurekaClientConfig;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired
private EurekaClient eurekaClient;
private EurekaClient eurekaClient;
EurekaClientAutoConfiguration 配置类 中实例化的
@Autowired
private InstanceRegistryProperties instanceRegistryProperties;
private InstanceRegistryProperties instanceRegistryProperties;
实例化
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
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
public HasFeatures eurekaServerFeature()
public HasFeatures eurekaServerFeature()
核心代码
@Bean
public HasFeatures eurekaServerFeature() {
return HasFeatures.namedFeature("Eureka Server",
EurekaServerAutoConfiguration.class);
}
public HasFeatures eurekaServerFeature() {
return HasFeatures.namedFeature("Eureka Server",
EurekaServerAutoConfiguration.class);
}
就是创建了一个 名称和EurekaServerAutoConfiguration key value 对应关系的一个对象
我们可以自己 添加映射关系
EurekaClientAutoConfiguration 配置类 里面也有这么类型的一个对象
@Bean
public HasFeatures eurekaFeature() {
return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
}
public HasFeatures eurekaFeature() {
return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
}
HasFeatures
源码
@Configuration
protected static class EurekaServerConfigBeanConfiguration
protected static class EurekaServerConfigBeanConfiguration
核心代码
@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;
}
}
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;
}
}
就是创建了EurekaServerConfig 的实例对象
@Bean
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
public EurekaController eurekaController()
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
public EurekaController eurekaController()
这个实际上就是Eureka 自带的一个Controller 类,对我提供暴露了一下接口
EurekaController
源码
@Bean
public ServerCodecs serverCodecs()
public ServerCodecs serverCodecs()
创建了一个编码解码器
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry
public PeerAwareInstanceRegistry peerAwareInstanceRegistry
初始化集群注册表
@Bean
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
ServerCodecs serverCodecs)
@ConditionalOnMissingBean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
ServerCodecs serverCodecs)
初始化集群节点集合
@Bean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes)
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes)
基于EurekaServer配置 注册表 集群节点集合 以及服务初始化EurekaServer上下文
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext)
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext)
核心方法
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
return new EurekaServerBootstrap(this.applicationInfoManager,
this.eurekaClientConfig, this.eurekaServerConfig, registry,
serverContext);
}
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
return new EurekaServerBootstrap(this.applicationInfoManager,
this.eurekaClientConfig, this.eurekaServerConfig, registry,
serverContext);
}
源码
这个是 EurekaServer 启动初始化的入口
流程
我们EurekaServerAutoConfiguration 配置类中的Bean 全部初始化之后
EurekaServerAutoConfiguration 的注解 @Import(EurekaServerInitializerConfiguration.class) 实现了SmartLifecycle 实现了这个接口的 会在项目启动后,调用start() 方法
start() 方法中调用了eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
初始化EurekaServer
核心代码
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);
}
}
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);
}
}
initEurekaEnvironment();
initEurekaServerContext();
int registryCount = this.registry.syncUp();
从相邻的eureka节点复制注册表
源码
Applications apps = eurekaClient.getApplications();
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
1. 修改eureka状态为up
2. 开启一个定时任务,清理60s没有 续约实例
2. 开启一个定时任务,清理60s没有 续约实例
@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// Renewals happen every 30 seconds and for a minute it should be a factor of 2.
this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold =
(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
logger.info("Got " + count + " instances from neighboring DS node");
logger.info("Renew threshold is: " + numberOfRenewsPerMinThreshold);
this.startupTime = System.currentTimeMillis();
if (count > 0) {
this.peerInstancesTransferEmptyOnStartup = false;
}
DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();
boolean isAws = Name.Amazon == selfName;
if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) {
logger.info("Priming AWS connections for all replicas..");
primeAwsReplicas(applicationInfoManager);
}
logger.info("Changing status to UP");
applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
super.postInit();
}
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
// Renewals happen every 30 seconds and for a minute it should be a factor of 2.
this.expectedNumberOfRenewsPerMin = count * 2;
this.numberOfRenewsPerMinThreshold =
(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
logger.info("Got " + count + " instances from neighboring DS node");
logger.info("Renew threshold is: " + numberOfRenewsPerMinThreshold);
this.startupTime = System.currentTimeMillis();
if (count > 0) {
this.peerInstancesTransferEmptyOnStartup = false;
}
DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName();
boolean isAws = Name.Amazon == selfName;
if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) {
logger.info("Priming AWS connections for all replicas..");
primeAwsReplicas(applicationInfoManager);
}
logger.info("Changing status to UP");
applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
super.postInit();
}
核心方法
primeAwsReplicas(applicationInfoManager);
super.postInit();
protected void postInit() {
renewsLastMin.start();
if (evictionTaskRef.get() != null) {
evictionTaskRef.get().cancel();
}
evictionTaskRef.set(new EvictionTask());
evictionTimer.schedule(evictionTaskRef.get(),
serverConfig.getEvictionIntervalTimerInMs(),
serverConfig.getEvictionIntervalTimerInMs());
}
renewsLastMin.start();
if (evictionTaskRef.get() != null) {
evictionTaskRef.get().cancel();
}
evictionTaskRef.set(new EvictionTask());
evictionTimer.schedule(evictionTaskRef.get(),
serverConfig.getEvictionIntervalTimerInMs(),
serverConfig.getEvictionIntervalTimerInMs());
}
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()))
发布注册中心启动事件
EurekaServerInitializerConfiguration.this.running = true
标记EurekaServer 处于运行中
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
注册中心服务启动事件
@Bean
public FilterRegistrationBean jerseyFilterRegistration(
javax.ws.rs.core.Application eurekaJerseyApp)
public FilterRegistrationBean jerseyFilterRegistration(
javax.ws.rs.core.Application eurekaJerseyApp)
实现过滤器的一种方式
实现过滤器有两种方式
通过FilterRegistrationBean实例注册
通过@WebFilter注解生效
第一种相对于第二种的优点是,可以自己设置过滤器之间的优先级
@Bean
public javax.ws.rs.core.Application jerseyApplication(Environment environment,
ResourceLoader resourceLoader)
public javax.ws.rs.core.Application jerseyApplication(Environment environment,
ResourceLoader resourceLoader)
@Bean
public FilterRegistrationBean traceFilterRegistration(
@Qualifier("webRequestLoggingFilter") Filter filter)
public FilterRegistrationBean traceFilterRegistration(
@Qualifier("webRequestLoggingFilter") Filter filter)
EurekaClientAutoConfiguration 是 springboot 启动的时候 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports 方法加载的
源码
核心代码
configurations = sort(configurations, autoConfigurationMetadata);
排序之后 我们发现 是先加载 EurekaClientAutoConfiguration 然后再加载EurekaServerAutoConfiguration
EurekaServerAutoConfiguration 配置类的很多@Autowired 注入的对象都是 在 EurekaClientAutoConfiguration 中实例化的
1
@Autowired
private ApplicationInfoManager applicationInfoManager;
private ApplicationInfoManager applicationInfoManager;
@Autowired
private EurekaClient eurekaClient;
private EurekaClient eurekaClient;
这两个是
2
@Autowired
private EurekaClientConfig eurekaClientConfig;
private EurekaClientConfig eurekaClientConfig;
@Bean
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
}
return client;
}
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
}
return client;
}
EurekaClientConfigBean
我们可以通过打断点发现 这个return 的client 和EurekaServerAutoConfiguration 注入的对象是同一个
0 条评论
下一页