Eureka源码分析之Eureka-Client(一)

一、前言

SpringCloud-Eureka组件是基于NetFlix的Eureka封装而成,故本系列源码是从Netflix/eureka角度分析,后续再分析Spring-cloud是如何封装Netflix/eureka的。

Netflix/eureka项目地址:https://github.com/Netflix/eureka,本系列文章的分析是基于2.x版本进行的。

 

二、eureka组成

使用过eureka的都应该清楚,eureka组件由eureka-client和eureka-server组成。client即客户端,像服务Provider和服务Consumer都属于client,而server也就是注册中心。

本文先分析eureka-client的初始化过程,后续文章再分析eureka-server相关。

 

三、eureka类关系图

本文重点就是讲述EurekaClient是如何创建以及这几个类(接口)的定义。

 

四、类/接口定义

1.1 EurekaInstanceConfig

从类名可以看出是一个配置类,默认的实现是MyDataCenterInstanceConfig,类结构图如下:

 

 

EurekaInstanceConfig接口:定义一些列获取配置信息的getter接口,下面列出一些常用的getter方法:

 1 getInstanceId()-实例ID,默认hostName:appName:port
 2 getAppname()-appName
 3 getAppGroupName()-分组名
 4 isInstanceEnabledOnit-eureka-client初始化后是否马上启动,默认false
 5 getLeaseRenewalIntervalInSeconds()-eureka-client向server续租频率,默认30s
 6 getLeaseExpirationDurationInSeconds()-租约过期时间,默认90s
 7 getHostName(boolean refresh)-hostName
 8 getIpAddress()-ipAddress
 9 getDataCenterInfo()-数据中心,默认为Name.MyOwn
10 getNamespace()-命名空间,默认eureka

 

1.2 AbstractInstanceConfig

抽象基类,主要定义了一些默认配置,下面列出部分,其余大家可以查看源码:

nameSpace=eureka
LEASE_EXPIRATION_DURATION_SECONDS = 90
LEASE_RENEWAL_INTERVAL_SECONDS = 30
INSTANCE_ENABLED_ON_INIT = false

 

1.3 PropertiesInstanceConfig

抽象类,主要功能是从属性配置文件eureka-client.properties读取配置信息,作为某些配置getter方法的返回值。

 

1.4 MyDataCenterInstanceConfig

EurekaInstanceConfig的默认实现,结构很简单,没什么逻辑。

@Singleton
@ProvidedBy(MyDataCenterInstanceConfigProvider.class)
public class MyDataCenterInstanceConfig extends PropertiesInstanceConfig implements EurekaInstanceConfig {

    public MyDataCenterInstanceConfig() {
    }

    public MyDataCenterInstanceConfig(String namespace) {
        super(namespace);
    }

    public MyDataCenterInstanceConfig(String namespace, DataCenterInfo dataCenterInfo) {
        super(namespace, dataCenterInfo);
    }

}

 

总结,EurekaInstanceConfig只是一个配置类,通过默认配置,读取配置文件提供一系列配置信息用来初始化InstanceInfo,关于InstanceInfo接口下面会讲到。

 

2.1 InstanceInfo

有上述的EurekaInstanceConfig生成,这个类很重要,当然字段也非常多,建议大家去看看源码,字段也和EurekaInstanceConfig的字段大致相同,毕竟是由它提供配置信息创建的。

为什么说这个类很重要,因为eureka-client向eureka-server注册中心注册的时候,就是注册这个类。

这个类除了一些配置信息外,内部还定义了一个实例状态枚举InstanceStatus,另外这个类的创建采用了Builder设计模式。

public enum InstanceStatus {
        UP, // Ready to receive traffic
        DOWN, // Do not send traffic- healthcheck callback failed
        STARTING, // Just about starting- initializations to be done - do not
        // send traffic
        OUT_OF_SERVICE, // Intentionally shutdown for traffic
        UNKNOWN;

        public static InstanceStatus toEnum(String s) {
            if (s != null) {
                try {
                    return InstanceStatus.valueOf(s.toUpperCase());
                } catch (IllegalArgumentException e) {
                    // ignore and fall through to unknown
                    logger.debug("illegal argument supplied to InstanceStatus.valueOf: {}, defaulting to {}", s, UNKNOWN);
                }
            }
            return UNKNOWN;
        }
    }

 

3.1 ApplicationInfoManager

这个类由InstanceInfo和EurekaInstanceConfig创建的,用来管理应用信息,注意,管理的是自身的InstanceInfo,而不是从eureka-server拉取过来的InstanceInfo!构造方法如下:

@Inject
    public ApplicationInfoManager(EurekaInstanceConfig config, InstanceInfo instanceInfo, OptionalArgs optionalArgs) {
        this.config = config;
        this.instanceInfo = instanceInfo;
        this.listeners = new ConcurrentHashMap<String, StatusChangeListener>();
        if (optionalArgs != null) {
            // 一般为NO_OP_MAPPER
            this.instanceStatusMapper = optionalArgs.getInstanceStatusMapper();
        } else {
            this.instanceStatusMapper = NO_OP_MAPPER;
        }

        // Hack to allow for getInstance() to use the DI'd ApplicationInfoManager
        instance = this;
    }

上述的源码中,OptionalArgs用于提供InstanceStatusMapper,这个类的作用是传入一个InstanceStatus,根据一定规则返回一个InstanceStatus,一般会采用NO_OP_MAPPER,也就是不处理,所以不用放太多注意力在这个类(其实我也没搞懂这个类有什么用)。此外还有一个属性listeners=new ConcurrentHashMap<String, StatusChangeListener>,主要用于监听自身InstanceInfo状态的改变,来进行下一步操作。

public static interface StatusChangeListener {
        String getId();

        void notify(StatusChangeEvent statusChangeEvent);
    }

此外,ApplicationInfoManager还提供了两个方法

refreshDataCenterInfoIfRequired()

refreshLeaseInfoIfRequired()

这个两个方法主要是根据配置信息(EurekaInstanceConfig)刷新当前自身InstanceInfo的IP&hostName和租约信息。这个目前我也不会用,因为正常操作下这些信息一般都是和配置信息一致的,个人估计和Spring-cloud-config这个组件有关,因为这个组件可以动态刷新配置信息。

 

4.1 EurekaClientConfig

这个接口也是配置接口,默认实现类为DefaultEurekaClientConfig。

这个配置和EurekaInstanceConfig不同之处在于,这个是用来配置EurekaClient的,里面大多配置都是和Eureka-Server交互相关,而EurekaInstanceConfig是用来配置InstanceInfo的,InstanceInfo主要提供注册信息到注册中心,如appName, hostName&ipAddress,租约信息等。下面给出部分配置属性:

getRegistryFetchIntervalSeconds() -- eureka-client从注册中心拉取InstanceInfo的频率,默认30s
getInstanceInfoReplicationIntervalSeconds() -- 自身InstanceInfo同步到注册中心的频率,默认30s
getInitialInstanceInfoReplicationIntervalSeconds() -- 自身InstanceInfo同步到注册中心时(第一次)的延迟时间(因为采用定时任务,所以是延迟执行时间),默认40s
shouldGZipContent() -- GZip压缩相关,默认true
getEurekaServerReadTimeoutSeconds() -- 从eureka-server读超时时间,8s
getEurekaServerConnectTimeoutSeconds() -- eureka-client连接到eureka-server的超时时间,默认5s
getBackupRegistryImpl() -- 备份注册中心,目前没有实现,不需太关注
shouldRegisterWithEureka() -- 是否注册到注册中心,默认true
shouldUnregisterOnShutdown() -- 自身服务关闭时是否发送下线信息到eureka-server,默认true
shouldPreferSameZoneEureka() -- 是否使用相同zone的eureka-server,默认true
shouldDisableDelta() -- 是否禁用增量拉取服务,默认false。意思是eureka-client从注册中心定时去拉取任务时,是全部都拉取过来,还是拉取最近增加的服务。
getRegion() -- 获取region,默认是us-east-1
getAvailabilityZones(String region) -- 返回一个String[],正常情况都是使用defaultZone。
shouldFilterOnlyUpInstances -- 过滤UP状态的实例,默认true
shouldFetchRegistry() -- 是否从注册中心拉取服务,默认true
EurekaTransportConfig getTransportConfig() -- 和HttpClient通讯相同
getHeartbeatExecutorThreadPoolSize() -- 心跳线程池大小,默认5?
getHeartbeatExecutorExponentialBackOffBound() -- 心跳定时任务执行失败的延迟重试时间,默认10s
getCacheRefreshExecutorThreadPoolSize() -- 缓存刷新线程池大小,默认5
getCacheRefreshExecutorExponentialBackOffBound() -- 缓存刷新定时任务失败的延迟重试时间,默认默认10s

 

4.2 DefaultEurekaClientConfig

EurekaClientConfig的默认实现,还是老规矩,从eureka-client.properties配置文件读取配置信息提供给香瓜你的getter方法。

另外有个EurekaTransportConfig属性,主要是用来配置eureka-client和eureka-server的网络传输相关配置,采用的硬编码配置。

 

5、总结

1、EurekaInstanceConfig和EurekClientConfig都是最顶层的接口,主要是通过硬编码+从配置文件读取配置信息来创建相关的配置类。

2、InstanceInfo主要用于提供自身服务信息注册到注册中心,而EurekaClientConfig主要是用来配置和注册中心交互通讯相关的配置,两者功能性不一样。

3、以上的一切一切都是为了用来创建本文的主角EurekaClient,为什么我不接下去说?因为这个创建过程太复杂,需要比较多的篇幅去描述,下文分析。

posted @ 2018-11-20 22:23  SingleDogs  阅读(193)  评论(0编辑  收藏  举报