Eureka源码分析之 Client的启动流程

Eureka Client 启动流程
本文详细解析了Eureka Client的启动流程,包括服务注册、续约、下线及服务获取等关键步骤,展示了如何通过Spring Boot注解激活DiscoveryClient,并深入分析了Eureka Discovery Client的初始化过程。

Eureka源码分析之 Client的启动流程

​ Eureka Client 是一个Java 客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的、使用轮询负载算法的负载均衡器。

​ 在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒),如果Eureka Server在多个心跳周期没有收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)。Eureka Client具有缓存的机制,即使所有的Eureka Server 都挂掉的话,客户端依然可以利用缓存中的信息消费其它服务的API。下面一起来看Client客户端相关操作的流程图。

在这里插入图片描述

图一 Client启动工作流程概览

1.从启动类入手

​ 从启动类的@EnableDiscoveryClient注解入手看调用流程。进入 EnableDiscoveryClient 之后,通过注释知道它的作用是为了激活 DiscoveryClient:

在这里插入图片描述

图二 DiscoveryClient注解图

​ 首先是在类头使用了 import 注解引入了:EnableDiscoveryClientImportSelector。该类的主要作用是实例化:AutoServiceRegistrationConfiguration。

@Order(Ordered.LOWEST_PRECEDENCE - 100)

public class EnableDiscoveryClientImportSelector

 extends SpringFactoryImportSelector<EnableDiscoveryClient> {

 

 @Override

 public String[] selectImports(AnnotationMetadata metadata) {

     **//调用父类的方法,拿到通过父类方法要注入的全路径类名数组**

 String[] imports = super.selectImports(metadata);

 **//获得该注解(@EnableDiscoveryClient)的所有属性参数**

 AnnotationAttributes attributes = AnnotationAttributes.fromMap(

  metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));

  **//获得属性autoRegister的值,该值默认是true的**

 boolean autoRegister = attributes.getBoolean("autoRegister");

 **//根据注解配置来判断是否要实例化下面的那个自动配置类**

 if (autoRegister) {

  List<String> importsList = new ArrayList<>(Arrays.asList(imports));

  importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");

  imports = importsList.toArray(new String[0]);

 } else {

  Environment env = getEnvironment();

  if(ConfigurableEnvironment.class.isInstance(env)) {

  ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;

  LinkedHashMap<String, Object> map = new LinkedHashMap<>();

  map.put("spring.cloud.service-registry.auto-registration.enabled", false);

  MapPropertySource propertySource = new MapPropertySource(

   "springCloudDiscoveryClient", map);

  configEnv.getPropertySources().addLast(propertySource);

  }

 }
 
 return imports;

 }


 @Override

 protected boolean isEnabled() {

 return getEnvironment().getProperty(

  "spring.cloud.discovery.enabled", Boolean.class, Boolean.TRUE);

 }


 @Override

 protected boolean hasDefaultFactory() {

 return true;

 }


}

这里最终的目的是想实例化:AutoServiceRegistrationConfiguration,我们来看他做了什么:

@Configuration

@Import(AutoServiceRegistrationConfiguration.class)

@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)

public class AutoServiceRegistrationAutoConfiguration {

 
 @Autowired(required = false)

 private AutoServiceRegistration autoServiceRegistration;

 @Autowired

 private AutoServiceRegistrationProperties properties;

 @PostConstruct

 protected void init() {

 if (autoServiceRegistration == null && this.properties.isFailFast()) {

  throw new IllegalStateException("Auto Service Registration has been requested, but there is no AutoServiceRegistration bean");

 }

 }

}

从这里看主要目的是为了实例化:AutoServiceRegistration,AutoServiceRegistrationProperties这两个类。那么初始化这两个bean的作用是什么呢,查看调用的地方:

@Configuration

@EnableConfigurationProperties

@ConditionalOnClass(EurekaClientConfig.class)

@Import(DiscoveryClientOptionalArgsConfiguration.class)

@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)

@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)

@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,

 CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })

@AutoConfigureAfter(name = {"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",

 "org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",

 "org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration"})

public class EurekaClientAutoConfiguration {

  ......

  ......

  ......

  @Bean

 @ConditionalOnBean(AutoServiceRegistrationProperties.class)

 @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)

 public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager, ObjectProvider<HealthCheckHandler> healthCheckHandler) {

 return EurekaRegistration.builder(instanceConfig)

  .with(applicationInfoManager)

  .with(eurekaClient)

  .with(healthCheckHandler)

  .build();

 }

 

 @Bean

 @ConditionalOnBean(AutoServiceRegistrationProperties.class)

 @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)

 public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {

 return new EurekaAutoServiceRegistration(context, registry, registration);

 }  

  ......

  ......

  ......

}

原因是在这里实例化bean的时候被作为前置条件。

EurekaClientAutoConfiguration 算是到目前为止比较重要的一个类,主要做的事情包括:

  1. 注册 EurekaClientConfigBean ,初始化client端配置信息;

  2. 注册 EurekaInstanceConfigBean ,初始化客户端实例信息;

  3. 初始化 EurekaRegistration,EurekaServiceRegistry,EurekaAutoServiceRegistration实现Eureka服务自动注册;

  4. 初始化 EurekaClient ,ApplicationInfoManager。EurekaClient 的默认实现是 DiscoveryClient,是我们接下来要分析的重点;

  5. 初始化 EurekaHealthIndicator,为/health 端点提供Eureka相关信息,主要有Status当前实例状态和applications服务列表。

继续看 EurekaClientAutoConfiguration 又在哪里被使用:

@ConditionalOnClass(ConfigServicePropertySourceLocator.class)

@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)

@Configuration

@Import({ EurekaDiscoveryClientConfiguration.class, **// this emulates @EnableDiscoveryClient, the import selector doesn't run before the bootstrap phase**

 EurekaClientAutoConfiguration.class })

public class EurekaDiscoveryClientConfigServiceBootstrapConfiguration {

}

在 EurekaDiscoveryClientConfigServiceBootstrapConfiguration 类中被作为注入的对象。

而 EurekaDiscoveryClientConfigServiceBootstrapConfiguration 被引用的分地方就比较特殊,被配置在配置文件中。

org.springframework.cloud.bootstrap.BootstrapConfiguration=\

org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration

这个配置的Key部分对应着一个注解类 BootstrapConfiguration:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface BootstrapConfiguration {

 **/****

 \* Exclude specific auto-configuration classes such that they will never be applied.

 */

 Class<?>[] exclude() default {};

}

他被使用的地方是:BootstrapApplicationListener 的 164行,在这里拿到类的全路径之后,186行进行加载类。

public class BootstrapApplicationListener

 implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {

  

  ......

  @Override

 public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {

 ConfigurableEnvironment environment = event.getEnvironment();

 ......

 ConfigurableApplicationContext context = null;

 String configName =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值