1-3 Eureka Client 客户端源码解析

本文详细解析了Eureka Client的工作流程,包括初始化阶段(读取配置、服务注册、发送心跳)、配置信息类(EurekaDiscoveryClientConfiguration、DiscoverClient等)以及DiscoverClient的构造方法、拉取注册表信息、服务注册和定时任务的初始化。通过源码解读,深入理解Eureka Client如何与Server交互、维护服务注册和心跳机制。
摘要由CSDN通过智能技术生成

一、客户端工作流程

1.1、初始化阶段

  • 1、读取与server交互的信息,封装成EurekaClientConfig
  • 2、读取自身服务信息,封装成EurekaInstanceConfig
  • 3、拉取Server注册信息缓存到本地
  • 4、服务注册
  • 5、发送心跳,刷新缓存,注册定时任务

1.2、启动阶段

  • 1、发送心跳维持租约
  • 2、定时获取注册表信息更新本地缓存
  • 3、监控自身信息,如果有变化重新注册服务

1.3、注销阶段

  • 从server端注销服务

二、配置信息类

2.1、EurekaDiscoveryClientConfiguration

  • 作用:帮助Client维持必要bean的属性读取和配置
2.1.1 读取属性和配置类
  • EurekaClientConfig:封装了与server交互的信息
  • ApplicationInfoManager:应用信息管理器,管理InstanceInfo,EurekaInstanceConfig
  • InstanceInfo:发送到server进行注册的元数据
  • EurekaInstanceConfig:自身服务实例的配置信息,用于构建InstanceInfo
  • DiscoverClient:用于服务发现的客户端接口

2.2、DiscoverClient

  • 说明:是服务端发现的核心接口
  • String description():获取实现类的描述
  • List getInstances(String serviceId):通过服务id获取服务信息
  • List getServices():获取服务id列表
package org.springframework.cloud.client.discovery;

public interface DiscoveryClient {

    String description();

    List<ServiceInstance> getInstances(String serviceId);

    List<String> getServices();

}
2.3、EurekaDiscoveryClient
  • 继承了DiscoveryClient,组合EurekaClient实现接口功能
package org.springframework.cloud.netflix.eureka;

public class EurekaDiscoveryClient implements DiscoveryClient {}

三、DiscoverClient类结构

3.1、DiscoveryClient

  • 包名:com.netflix.discovery.DiscoveryClient
  • 说明:Client端与Server端交互关键逻辑
3.1.1、功能
  • 1、注册服务到Server
  • 2、发送心跳更新租约
  • 3、服务关闭时从Server中取消租约下线服务
  • 4、查询在Server中注册的服务实例列表

package com.netflix.discovery;

@Singleton
public class DiscoveryClient implements EurekaClient {}

3.1.2、类体系

LookupService—> EurekaClient ----> DiscoveryClient

3.2、LookupService

  • Application getApplication(String appName):通过服务名称获取实例信息
  • Applications getApplications():获取实例列表
  • List getInstancesById(String id):通过服务id获取服务信息
package com.netflix.discovery.shared;

public interface LookupService<T> {

    Application getApplication(String appName);

    Applications getApplications();

    List<InstanceInfo> getInstancesById(String id);

    InstanceInfo getNextServerFromEureka(String virtualHostname, boolean secure);
}

3.3、Application

  • Application中对InstanceInfo的操作都是同步
  • Applications里面的操作基本也是同步操作
3.3.1、Application所有属性
package com.netflix.discovery.shared;

@Serializer("com.netflix.discovery.converters.EntityBodyConverter")
@XStreamAlias("application")
@JsonRootName("application")
public class Application {
   
    private static Random shuffleRandom = new Random();
    private String name;
   
    private volatile boolean isDirty = false;
    private final Set<InstanceInfo> instances;
    private final AtomicReference<List<InstanceInfo>> shuffledInstances;
    private final Map<String, InstanceInfo> instancesMap;
}
3.3.2、Application操作同步
private void removeInstance(InstanceInfo i, boolean markAsDirty) {
        instancesMap.remove(i.getId());
        synchronized (instances) {
            instances.remove(i);
            if (markAsDirty) {
                isDirty = true;
            }
        }
    }

3.4、EurekaClient

  • 特点:继承了LookupService,为DiscoveryClient提供了上层接口,属于比较稳定的接口(扩展层)
3.4.1、作用
  • 提供了多种获取InstanceInfo接口
  • 提供了本地客户端数据
  • 提供了为客户端注册和获取健康检查处理器的能力
3.4.2、核心方法
  • 为Eureka Client注册健康检查处理器
  • 监听Client服务实例信息的更新
    //为Eureka Client注册健康检查处理器
    public void registerHealthCheck(HealthCheckHandler healthCheckHandler);
    //监听Client服务实例信息的更新
    public void registerEventListener(EurekaEventListener eventListener);

3.5、HealthCheckHandler

  • 用于检查当前Client的状态,如果Client的姿态发生改变,将会触发新的注册事件
  • 该事件属于观察者模式,事件监听器将监听Client的服务实例信息变化,触发对应的处理事件
public interface HealthCheckHandler {

    InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus);

}

四、、DiscoverClient 源码解读

4.1、DiscoverClient构造方法

@Inject
    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                    Provider<BackupRegistry> backupRegistryProvider)
4.1.1、构造方法参数

参数说明

  • ApplicationInfoManager:应用信息管理器
  • EurekaClientConfig:Client与Server交互配置信息
  • AbstractDiscoveryClientOptionalArgs:注入可选参数
  • Provider:用于获取注册表信息
4.1.2、构造方法主要操作
  • 从Server中拉取注册表信息,服务信息,初始化发送心跳,刷新缓存,按需注册定时任务
  • 1、初始化阶段:基础信息初始化,配置信息初始化,线程池初始化
  • 2、构建阶段:构建EurekaTransport
  • 3、预处理阶段:拉取Server注册表信息,注册前预处理
  • 4、注册阶段:向Server中注册,初始化心跳定时任务(线程池2个线程)
    @Inject
    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                    Provider<BackupRegistry> backupRegistryProvider) {
    //1、参数说明
    //ApplicationInfoManager:应用信息管理器
    //EurekaClientConfig:Client与Server交互信息
    //AbstractDiscoveryClientOptionalArgs:可选参数
    //Provider<BackupRegistry>:注册中心备份
   
   
    //2、初始化信息
        if (args != null) {
            this.healthCheckHandlerProvider = args.healthCheckHandlerProvider;
            this.healthCheckCallbackProvider = args.healthCheckCallbackProvider;
            this.eventListeners.addAll(args.getEventListeners());
            this.preRegistrationHandler = args.preRegistrationHandler;
        } else {
            this.healthCheckCallbackProvider = null;
            this.healthCheckHandlerProvider = null;
            this.preRegistrationHandler = null;
        }
       
        this.applicationInfoManager = applicationInfoManager;
        InstanceInfo myInfo = applicationInfoManager.getInfo();

        clientConfig = config;
        staticClientConfig = clientConfig;
        transportConfig = config.getTransportConfig();
        instanceInfo = myInfo;
        if (myInfo != null) {
            appPathIdentifier = instanceInfo.getAppName() + "/" + instanceInfo.getId();
        } else {
            logger.warn("Setting instanceInfo to a passed in null value");
        }

        this.backupRegistryProvider = backupRegistryProvider;

        this.urlRandomizer = new EndpointUtils.InstanceInfoBasedUrlRandomizer(instanceInfo);
        localRegionApps.set(new Applications());

        fetchRegistryGeneration = new AtomicLong(0);

        remoteRegionsToFetch = new AtomicReference<String>(clientConfig.fetchRegistryForRemoteRegions());
        remoteRegionsRef = new AtomicReference<>(remoteRegionsToFetch.get() == null ? null : remoteRegionsToFetch.get().split(","));


    //3、配置信息读取初始化
    //shouldFetchRegistry对应配置:eureka.client.fetch-register=true/false(是否从Server中拉取注册表信息)
    //shouldRegisterWithEureka对应配置:eureka.client.register-with-eureka=true/false(是否将自身信息注册到Server)
      
        if (config.shouldFetchRegistry()) {
            this.registryStalenessMonitor = new ThresholdLevelsMetric(this, METRIC_REGISTRY_PREFIX + "lastUpdateSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
        } else {
            this.registryStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
        }

        if (config.shouldRegisterWithEureka()) {
            this.heartbeatStalenessMonitor = new ThresholdLevelsMetric(this, METRIC_REGISTRATION_PREFIX + "lastHeartbeatSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
        } else {
            this.heartbeatStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
        }

        logger.inf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值