SpringCloud源码阅读2-Eureka客户端的秘密(下)

简介: SpringCloud源码阅读2-Eureka客户端的秘密(下)

2.1.4 InstanceInfoReplicator.run()

public void run() {
        try {
          //1.刷新DataCenterInfo
          //2.刷新LeaseInfo 租约信息
          //3.从HealthCheckHandler中获取InstanceStatus
            discoveryClient.refreshInstanceInfo();
      //如果isInstanceInfoDirty=true表明需要更新,返回dirtyTimestamp。
            Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
            if (dirtyTimestamp != null) {
                discoveryClient.register();//注册。
                instanceInfo.unsetIsDirty(dirtyTimestamp);//注册完成,设置没有更新。
            }
        } catch (Throwable t) {
            logger.warn("There was a problem with the instance info replicator", t);
        } finally {
            Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
            scheduledPeriodicRef.set(next);
        }
    }

可以看出实例注册就在discoveryClient.register()

那么第一次注册发生在什么时候呢?

initScheduledTasks方法中,执行instanceInfoReplicator.start时,会首先调用instanceInfo.setIsDirty(),初始化是否更新标志位为ture ,开启线程,40秒后发起第一次注册。(当然如果在这40秒内,如果有状态变化,会立即发起注册。)


2.1.4 discoveryClient.register()

boolean register() throws Throwable {
        logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
        EurekaHttpResponse<Void> httpResponse;
        try {
          //发起注册
            httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
        } catch (Exception e) {
            logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
            throw e;
        }
        if (logger.isInfoEnabled()) {
            logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
        }
        return httpResponse.getStatusCode() == 204;
    }

可以看出,register方法本质也是通过eurekaTransport 来发起与server的通信的。


2.2EurekaClient卸载方法

2.2.1shutdown()

注解@PreDestroy修饰的shutdown()会在Servlet被彻底卸载之前执行。

public synchronized void shutdown() {
        if (isShutdown.compareAndSet(false, true)) {
            logger.info("Shutting down DiscoveryClient ...");
      //移除监听
            if (statusChangeListener != null && applicationInfoManager != null) {
                applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
            }
      //取消任务
            cancelScheduledTasks();
            // If APPINFO was registered
            if (applicationInfoManager != null
                    && clientConfig.shouldRegisterWithEureka()
                    && clientConfig.shouldUnregisterOnShutdown()) {
                applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
                //下线
                unregister();
            }
      //通信中断
            if (eurekaTransport != null) {
                eurekaTransport.shutdown();
            }
            heartbeatStalenessMonitor.shutdown();
            registryStalenessMonitor.shutdown();
            logger.info("Completed shut down of DiscoveryClient");
        }
    }


3.EurekaAutoServiceRegistration回调


EurekaAutoServiceRegistration实现了SmartLifecycle,会在spring启动完毕后,调用其start()方法。

@Override
  public void start() {
    // 设置端口
    if (this.port.get() != 0) {
      if (this.registration.getNonSecurePort() == 0) {
        this.registration.setNonSecurePort(this.port.get());
      }
      if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
        this.registration.setSecurePort(this.port.get());
      }
    }
    if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
      //注册
      this.serviceRegistry.register(this.registration);
      //发布注册成功事件
      this.context.publishEvent(
          new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));
      this.running.set(true);//
    }
  }

this.serviceRegistry.register(this.registration);

@Override
  public void register(EurekaRegistration reg) {
    maybeInitializeClient(reg);
    // 更改状态,会触发监听器的执行
    reg.getApplicationInfoManager()
        .setInstanceStatus(reg.getInstanceConfig().getInitialStatus());
    reg.getHealthCheckHandler().ifAvailable(healthCheckHandler ->
        reg.getEurekaClient().registerHealthCheck(healthCheckHandler));
  }


4.总结


1.注册流程

EurekaAutoServiceRegistration.start()

-->EurekaServiceRegistry.register(EurekaRegistration)

-->ApplicationInfoManager.setInstanceStatus 状态改变,

-->StatusChangeListener 监听器监听到状态改变

-->InstanceInfoReplicator.onDemandUpdate() 更新状态到server

-->InstanceInfoReplicator.run()

-->DiscoveryClient.register()

-->eurekaTransport.registrationClient.register(instanceInfo);

-->jerseyClient


2.客户端初始化的几个定时任务

  • 缓存刷新任务,默认30秒
  • 心跳任务,默认30秒
  • 信息更新任务,默认40秒


3.客户端的几个主要操作:

  • 服务注册(register)
  • 服务续约(renew)
  • 服务下线(unregister)
  • 服务获取(fetchRegistry)
  • 缓存刷新(refreshRegistry)

由于篇幅原因,很多细节不能一一展示。本文志在说说一些原理,具体细节可以研读源码,会发现框架真优秀啊。


相关文章
|
11天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
46 5
|
2月前
|
负载均衡 算法 Nacos
SpringCloud 微服务nacos和eureka
SpringCloud 微服务nacos和eureka
67 0
|
2月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
47 0
|
3月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
4月前
|
Java Spring
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
|
4月前
|
Java Spring 容器
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
|
4月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
4月前
|
SQL Java 数据库连接
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
|
4月前
|
Java 开发工具 Spring
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
|
4月前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常