个人随笔
目录
九、Eureka服务注册应用未启动就注册导致服务访问失败的原因分析!
2021-02-18 17:49:11

背景

在生产环境,每次换完版,都发现zuul的日志有服务拒绝连接的情况,表明服务根本就没有启动成功,初步怀疑是没有优雅的下线微服务导致的。

优雅的下线微服务

通过Eureka提供的端点,进行优雅的下线微服务,并且暂停40s等服务消费者从新从Eureka获取服务列表(默认30s),后面才kill掉服务(最好的方式是等应用没有流量进来再kill掉微服务),然后进行重启。

发现重启完后zuul还是会有几个这样拒绝连接的日志!

原因猜测

会不会是SpringCloud在启动的过程中,应用还没有启动完就向Eureka服务端注册服务,然后导致在发送注册消息到应用真正启动完的时间段内,请求进来会报拒绝连接的错误,这个得查看源码才能知道。

源码分析

有了解过SpringBoot自动配置的同学应该知道,在主程序启动类上我们会贴一个 @SpringBootApplication 注解,该注解里面包含了一个 @EnableAutoConfiguration 注解,该注解的作用是开启SpringBoot的自动配置,即:在 @EnableAutoConfiguration 标签中使用了一个 AutoConfigurationImportSelector 选择器,该选择器会去扫描当前classpath环境中的 META-INF/spring.factories 文件中的自动配置类,然后完成相关的自动配置。

在 selectImports 方法中会将扫描到的 META-INF/spring.factories 文件中的自动配置的一些类加载进来,然后注册到Spring容器中

其中在 spring-cloud-netflix-eureka-client-2.0.1.RELEASE.jar 这个jar包里面就有一个 META-INF/spring.factories文件,内容如下:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
  3. org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\
  4. org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
  5. org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
  6. org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration

我们这里需要重点关注是 EurekaClientAutoConfiguration 这个类,从名字就能看出它是对EureakClient的自动配置,可以看到有如下代码

  1. //注册Eureak客户端EurekaClient, @Lazy 懒初始化,该bean被用到的时候会被创建
  2. //EurekaClient有一个实现 DiscoveryClient这个实现 是eureka-client:1.9.3包里面的,是Euraek的服务发现的核心实现
  3. @Bean(destroyMethod = "shutdown")
  4. @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
  5. @org.springframework.cloud.context.config.annotation.RefreshScope
  6. @Lazy
  7. public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) {
  8. manager.getInfo(); // force initialization
  9. return new CloudEurekaClient(manager, config, this.optionalArgs,
  10. this.context);
  11. }

但是这里有个注解@Lazy,延迟加载,也就是不是在这里初始化的,我们再看EurekaAutoServiceRegistration,这个类实现了SmartLifecycle,然后在应用启动后就会自动调用start方法,代码如下:

  1. @Override
  2. public void start() {
  3. // only set the port if the nonSecurePort or securePort is 0 and this.port != 0
  4. if (this.port.get() != 0) {
  5. if (this.registration.getNonSecurePort() == 0) {
  6. this.registration.setNonSecurePort(this.port.get());
  7. }
  8. if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
  9. this.registration.setSecurePort(this.port.get());
  10. }
  11. }
  12. // only initialize if nonSecurePort is greater than 0 and it isn't already running
  13. // because of containerPortInitializer below
  14. if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
  15. //调用服务注册器进行服务注册
  16. this.serviceRegistry.register(this.registration);
  17. //发布一个服务注册事件
  18. this.context.publishEvent(
  19. new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));
  20. this.running.set(true);
  21. }
  22. }

可以知道,这里也进行了加载,所以是在应用启动后才去注册的,应该没问题啊!

那为什么还会出现上面的问题?

原来,项目里的微服务Eureka版本是1.2.6,springcloud还没有加上EurekaAutoServiceRegistration类,然后是靠自动配置类的如下代码:

  1. @Bean
  2. public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) {
  3. return new EurekaDiscoveryClient(config, client);
  4. }

第二个入参是com.netflix.discovery.EurekaClient类型,此对象同样来自EurekaClientAutoConfiguration类,如下方法:

  1. @Bean(destroyMethod = "shutdown")
  2. @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
  3. @org.springframework.cloud.context.config.annotation.RefreshScope
  4. @Lazy
  5. public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) {
  6. manager.getInfo(); // force initialization
  7. return new CloudEurekaClient(manager, config, this.optionalArgs,this.context);
  8. }

疑问,我看新版本的Eureka也有上面的方法,那为啥还要EurekaAutoServiceRegistration这个,要了也没有意义啊!这里真是搞不懂了,只能够推测新版本的这段逻辑不会执行!

 1333

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2