天天看点

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

1.预备知识

1.1 Region 与 Zone

1.1.1 概念

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

Eureka 中具有 Region 与 Availability Zone(简称 AZ)概念,是云计算中的概念。

为了方便不同地理区域中用户的使用

,大型云服务提供商一般会根据用户需求量在不同的城市、省份、国家或洲创建不同的大型云计算机房。这些不同区域机房间一般是不能“内网连通”的。这些区域就称为一个 Region。

这里存在一个问题:同一 Region 机房是如何实现

同域容灾

的?为了增强容灾能力,在一个 Region 中又设置了不同的

Availability Zone

。这些 AZ 间实现了

内网连通

,且用户可以根据自己所在的具体位置自动选择同域中的不同 AZ。当用户所要访问的 AZ 出现问题后,系统会自动切换到其它可用的 AZ。

例如,AWS 将全球划分为了很多的 Region,例如美国东部区、美国西部区、欧洲区、非洲开普敦区、亚太区等。像 Eureka 系统架构图中的 us-east-1c、us-east-1d、us-east-1e 就是 us-east-1 这个 Region 中的 c、d、e 三个 AZ。

再如,阿里云在我国境内的 Region 有杭州、北京、深圳、青岛、香港等,境外 Region有亚太东南 1 区(新加坡)、亚太东南 2 区(悉尼)、亚太东北 1 区(东京)。

1.1.2 Eureka 中的 Region 与 Zone 配置

(1) 需求

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

假设某公司的服务器有 Beijing、Shanghai 等多个 Region。Beijing 这个 Region 中存在两个 AZ,分别是 bj-1 与 bj-2,每个 AZ 中有三台 Eureka Server。

h-1 与 h-2 两台主机提供的都是相同的 Servivce 服务,根据地理位置的不同,这两台主机分别注册到了距离自己最近的不同 AZ 的 Eureka Server。

但是因为Region中的AZ都是内网联通的,所以 整个Region中的每个Eureka Server数据都是一致的。

(2) 主机配置

Eureka配置:

  • A、Server AZ bj-1

    说明:bj-1 这个 Eureka Server 的 AZ 集群中具有三台 Server,这三台 Server 的配置文件,除了 server.port 不同外,其它配置完全相同。

    这三个 Server 的 IP 与端口分别为:ip00:8000,ip01:8001,ip02:8002,该三台主机属于同一个zone。

    同时需要注意,defaultZone需要配置整个Region中所有的Eureka Server的地址

    配置如下,只展示了一个,另外两个只是端口不同,可以看到是通过元数据配置zone的:

    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • B、 Server AZ bj-2

    说明:bj-2 这个 AZ 集群中具有三台 Server,这三台 Server 的配置文件,除了 server.port不同外,其它配置完全相同。

    这三个 Server 的 IP 与端口分别为:ip10:8000,ip11:8001,ip12:8002,该三台主机属于同一个zone。

    同时需要注意,defaultZone需要配置整个Region中所有的Eureka Server的地址

    配置如下,也是只展示了一个,另外两个只是端口不同:

    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

Zuul配置:

  • C、 Zuul AZ bj-1
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • D、Zuul AZ bj-2
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

Service配置:

这两个微服务名称是相同的,只是在不同的zone

  • E、 Service AZ bj-1
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • F、 Service AZ bj-2
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
可以通过以下配置,让Eureka Client优先选择相同zone的应用
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
如果当前region中的应用都不能用,可以用以下参数指定其他region
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

1.2 核心类

(1) InstanceInfo

简单来说,该类代表的就是注册表中的一个主机实例信息。每一个注册到Eureka Server的主机对应一个该类的实例。

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

两个时间戳:

后面分析源码会多次看到两个时间戳,先简单介绍一下:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • lastDirtyTimestamp:记录 instanceInfo 在

    Client 端

    被修改的时间。

    这个字段只会在client端被更新

    , instanceInfo 中任何信息被修改(数据中心信息、续约配置信息、状态等),都会更新该时间戳。
  • lastUpdatedTimestamp:记录 instanceInfo 在

    Server 端

    被修改的时间。

    这个字段只会在server端被更新

    ,server端通常只会修改 instanceInfo 的状态信息(我暂时只发现只修改了状态信息)。

两个状态:

instanceInfo中一共有两个状态overriddenStatus和status。

关于overriddenStatus,字面意思是覆盖状态,它是一个“外部”状态,可以由外部任何程序进行修改,例如之前演示服务平滑上下线,通过actuator修改服务器(主机实例)状态,修改的值其实就是overriddenStatus。而overriddenStatus并不代表服务器真正状态。

而status是真正的服务器状态,但是status的值是通过一套规则计算出来的,其中就需要overriddenStatus,后面分析源码会看到。

三个修改状态的方法:

  • setOverriddenStatus

    该方法仅会在 Eureka Server 端被调用。(通过actuator修改状态UP/DOWN…由客户端发起请求,服务端处理请求的时候调用)

    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • setStatusWithoutDirty

    该方法仅会在 Eureka Server 端被调用,在修改 status 时不记录修改时间戳。

    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • setStatus

    该方法在 Eureka Client 端调用(定时检测配置更新的时候),用于设置 instance 的服务状态。

    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
    //InstanceInfo.java
    /**
     * Set the status for this instance.
     *
     * @param status status for this instance.
     * @return the prev status if a different status from the current was set, null otherwise
     */
    public synchronized InstanceStatus setStatus(InstanceStatus status) {
        if (this.status != status) {
            InstanceStatus prev = this.status;//记录之前状态
            this.status = status;//更新新的状态
            setIsDirty();//设置dirty标志,脏数据标记,表示客户端和服务端之间数据不一致,需要同步
            return prev;//返回之前的状态
        }
        return null;
    }
    /**
     * Sets the dirty flag so that the instance information can be carried to
     * the discovery server on the next heartbeat.
     * 设置dirty标志,以便可以将实例信息传输到下一个heartbeat上的发现服务器。
     * 
     * 简单来说就是变成脏数据以后,客户端会发起请求和服务端进行数据同步,后面源码分析会看到
     */
    public synchronized void setIsDirty() {
        isInstanceInfoDirty = true;
        lastDirtyTimestamp = System.currentTimeMillis();
    }
               

看下都有哪些状态:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • UP:对外提供服务的 启动状态,

    Ribbon负载均衡的时候,只有当 status 的状态为 UP 时,才能被服务发现,进行服务调用

  • OUT_OF_SERVICE:和DOWN效果一样,但一般是我们手动通过actuator修改状态,让其不提供服务,当然手动修改为DOWN也可以
  • DOWN:一般不是手动修改,而是client和server心跳发生异常的时候,系统自动修改为DOWN
  • STARTING:client启动过程、初始化过程中的状态,启动完成后状态就变了,一般维持的时间不会很长
  • UNKNOWN:一般来说就是overriddenStatus的初始值
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

InstanceInfo重写了 equals()方法:

InstanceInfo重写了 equals()方法,将来两个InstanceInfo比较,主要看InstanceInfo的id:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

(2) Application

也是注册表中的一部分,简单来说,注册表中同一个微服务的所有提供者的实例InstanceInfo信息都会维护在该类中,即一种微服务对应一个Application实例。

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

(3) Applications

这个就是我们说的注册表,维护的是整个从服务端获取的注册表信息。

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

说明一点:这个类专门为客户端使用的,实际上服务端的注册表数据结构,就是一个双层map,后面源码分析会看到。

(4) Jersey 框架

Eureka Client 与 Eureka Server 间的通信,及各个 Eureka Server 间的通信,使用的是 Jersey 框架完成的(

都是通过http协议进行通信的

)。

Jersey 框架是一个开源的 RESTful 框架。其功能与 SpringMVC 的相同。不同的是 SpringMVC 的处理器是 Controller,而 Jersey 的是 Resource。

2. Eureka Client 自动配置类的加载

PS:对Spring boot自动配置不熟的朋友,可以先去看一下关于SpringBoot自动配置的文章。我的博客里也有。

这里我们主要关注Eureka Client自动配置的时候都加载了哪些东西

入口从Eureka Client依赖开始:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

找到对应的依赖的具体代码:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

Eureka Client相关配置类的加载

关于@EnableConfigurationProperties注解:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

可以看到对于@ConfigurationProperties的类的处理,可以直接在注解的value属性指定相应类名进行注册,或者通过 @Bean方法注册。EurekaClientAutoConfiguration是通过@Bean的方式:

  • EurekaClientConfig
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • EurekaInstanceConfig
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

Eureka Client 的创建

我们现在看我们最核心的EurekaClient的创建

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

问题1:

看下@ConditionalOnMissingBean注解的search属性:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

对应有三种策略:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

PS:当然判断的条件和Bean加载的顺序也有关,这个其实是SpringBoot自动配置的知识点,不是本篇重点。

问题2:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

在讲Spring Cloud Config自动更新配置的时候,其实用过这个注解,这个注解可以让Spring容器刷新的时候,让当前实例重新生成新的实例。

问题3:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

懒加载,简单来说就是如果不从Spring容器中获取这个bean实例,或者被其他实例引用,就不会对该bean进行初始化。

即只有用到的时候才会初始化。

问题4:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

看一下@ConditionalOnMissingRefreshScope注解:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • Conditional注解:
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
  • 看下具体的条件,OnMissingRefreshScopeCondition类:
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
    Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

回过头看@ConditionalOnRefreshScope注解对比以下,看到条件刚好是相反的:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

所以这两个内置配置类不会同时起作用:

Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载
Spring Cloud Eureka Client 源码解析(一)预备知识、自动配置类的加载解析1.预备知识2. Eureka Client 自动配置类的加载

继续阅读