eureka核心知识梳理

1 重要属性介绍

1.1 eureka.instance.lease-expiration-duration-in-seconds

leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance。
1.默认为90秒。
2.如果该值太大,则很可能将流量转发过去的时候,该instance已经不存活了。
3.如果该值设置太小了,则instance则很可能因为临时的网络抖动而被摘除掉。
4.该值至少应该大于leaseRenewalIntervalInSeconds

1.2 eureka.instance.lease-renewal-interval-in-seconds

leaseRenewalIntervalInSeconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外,如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量。默认30秒。

1.3 eureka.instance.prefer-ip-address

如果设置eureka.instance.prefer-ip-address为false时,那么注册到Eureka中的Ip地址就是本机的Ip地址。如果设置了true并且也设置了eureka.instance.ip-address那么就将此ip地址注册到Eureka中。那么调用的时候,发送的请求目的地就是此Ip地址。

1.4 eureka.server.eviction-interval-timer-in-ms

eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒

2 SpringCloud注册中心Eureka 集群是怎么保持数据一致的?

eureka服务注册中心,集群中的服务注册信息如何在集群中保持一致的呢?首先要明确的是 Eureka 是弱数据一致性的。下面从2个方面来说明:
什么是弱数据一致性
Eureka 是如何同步数据的

2.1 弱数据一致性

我们知道 ZooKeeper 也可以实现数据中心,ZooKeeper 就是强一致性的。分布式系统中有一个重要理论:CAP。
该理论提到了分布式系统中的3个特性:
.Consistency 数据一致性
分布式系统中,数据会存在多个副本中,有一些问题会导致写入数据时,一部分副本成功、一部分副本失败,造成数据不一致。满足一致性就要求对数据的更新操作成功后,多副本的数据必须保持一致。
.Availability 可用性
在任何时候客户端对集群进行读写操作时,请求能够正常响应。
.Partition Tolerance 分区容忍性
发生通信故障时,集群被分割为多个无法通信的分区时,集群仍然可用。

CAP 理论指出:这3个特性不可能同时满足,最多满足2个。
P 是客观存在的,不可绕过,那么就是选择 C 还是选择 A。
ZooKeeper 选择了 C,就是尽可能的保证数据一致性,某些情况下可以牺牲可用性。Eureka 则选择了 A,所以 Eureka 具有高可用性,在任何时候,服务消费者都能正常获取服务列表,但不保证数据的强一致性,消费者可能会拿到过期的服务列表。

Eureka 的设计理念:保留可用及过期的数据总比丢掉可用的数据好。

2.2 Eureka 的数据同步方式

2.2.1 复制方式

分布式系统的数据在多个副本之间的复制方式,主要有:
主从复制
就是 Master-Slave 模式,有一个主副本,其他为从副本,所有写操作都提交到主副本,再由主副本更新到其他从副本。写压力都集中在主副本上,是系统的瓶颈,从副本可以分担读请求。
对等复制
就是 Peer to Peer 模式,副本间不分主从,任何副本都可以接收写操作,然后每个副本间互相进行数据更新。对等复制模式,任何副本都可以接收写请求,不存在写压力瓶颈,但各个副本间数据同步时可能产生数据冲突。Eureka 采用的就是 Peer to Peer 模式。

2.2.2 同步过程

Eureka Server 本身依赖了 Eureka Client,也就是每个 Eureka Server 是作为其他 Eureka Server 的 Client。
Eureka Server 启动后,会通过 Eureka Client 请求其他 Eureka Server 节点中的一个节点,获取注册的服务信息,然后复制到其他 peer 节点。
Eureka Server 每当自己的信息变更后,例如 Client 向自己发起注册、续约、注销请求, 就会把自己的最新信息通知给其他 Eureka Server,保持数据同步。
在这里插入图片描述
如果自己的信息变更是另一个Eureka Server同步过来的,这是再同步回去的话就出现数据同步死循环了。
在这里插入图片描述
Eureka Server 在执行复制操作的时候,使用 HEADER_REPLICATION 这个 http header 来区分普通应用实例的正常请求,说明这是一个复制请求,这样其他 peer 节点收到请求时,就不会再对其进行复制操作,从而避免死循环。还有一个问题,就是数据冲突,比如 server A 向 server B 发起同步请求,如果 A 的数据比 B 的还旧,B 不可能接受 A 的数据,那么 B 是如何知道 A 的数据是旧的呢?这时 A 又应该怎么办呢?

数据的新旧一般是通过版本号来定义的,Eureka 是通过 lastDirtyTimestamp 这个类似版本号的属性来实现的。lastDirtyTimestamp 是注册中心里面服务实例的一个属性,表示此服务实例最近一次变更时间。
比如 Eureka Server A 向 Eureka Server B 复制数据,数据冲突有2种情况:
(1)A 的数据比 B 的新,B 返回 404,A 重新把这个应用实例注册到 B。
(2)A 的数据比 B 的旧,B 返回 409,要求 A 同步 B 的数据。

还有一个重要的机制:hearbeat 心跳,即续约操作,来进行数据的最终修复,因为节点间的复制可能会出错,通过心跳就可以发现错误,进行弥补。例如发现某个应用实例数据与某个server不一致,则server放回404,实例重新注册即可。

2.3 小结

1.Eureka 是弱数据一致性,选择了 CAP 中的 AP。
2.Eureka 采用 Peer to Peer 模式进行数据复制。
3.Eureka 通过 lastDirtyTimestamp 来解决复制冲突。
4.Eureka 通过心跳机制实现数据修复。

3 eureka分区

3.1 背景

用户量比较大或者用户地理位置分布范围很广的项目,一般都会有多个机房。这个时候如果上线springCloud服务的话,我们希望一个机房内的服务优先调用同一个机房内的服务,当同一个机房的服务不可用的时候,再去调用其它机房的服务,以达到减少延时的作用。

3.2 概念

eureka提供了region和zone两个概念来进行分区,这两个概念均来自于亚马逊的AWS:

1.region:可以简单理解为地理上的分区,比如亚洲地区,或者华北地区,再或者北京等等,没有具体大小的限制。根据项目具体的情况,可以自行合理划分region。
2.zone:可以简单理解为region内的具体机房,比如说region划分为北京,然后北京有两个机房,就可以在此region之下划分出zone1,zone2两个zone。

3.3 分区服务架构图

在这里插入图片描述
如图所示,有一个region:beijing,下面有zone-1和zone-2两个分区,每个分区内有一个注册中心Eureka Server和一个服务提供者Service。我们在zone-1内创建一个Consumer-1服务消费者的话,其会优先调用同一个zone内的Service-1,当Service-1不可用时,才会去调用zone-2内的Service-2。

3.4 相关配置介绍

整个分区分为两步:
1.服务注册:要保证服务注册到同一个zone内的注册中心,因为如果注册到别zone的注册中心的话,网络延时比较大,心跳检测很可能出问题。
2.服务调用:要保证优先调用同一个zone内的服务,只有在同一个zone内的服务不可用时,才去调用别zone的服务。

3.4.1 服务注册的配置文件

eureka:
  client:
    prefer-same-zone-eureka: true
    #地区
    region: beijing
    availability-zones:
      beijing: zone-1,zone-2
    service-url:
      zone-1: http://localhost:30000/eureka/
      zone-2: http://localhost:30001/eureka/

当一个服务(作为一个eureka client)向注册中心(eureka server)注册的时候,会根据eureka.client下的配置来进行注册。这里我们主要关心有多个注册中心的情况下,服务会注册到哪个注册中心,并且和哪个注册中心来维持心跳检测。

注册中心选择逻辑:

  1. 如果prefer-same-zone-eureka为false,按照service-url下的 list取第一个注册中心来注册,并和其维持心跳检测。不会再向list内的其它的注册中心注册和维持心跳。只有在第一个注册失败的情况下,才会依次向其它的注册中心注册,总共重试3次,如果3个service-url都没有注册成功,则注册失败。每隔一个心跳时间,会再次尝试。
  2. 如果prefer-same-zone-eureka为true,先通过region取availability-zones内的第一个zone,然后通过这个zone取service-url下的list,并向list内的第一个注册中心进行注册和维持心跳,不会再向list内的其它的注册中心注册和维持心跳。只有在第一个注册失败的情况下,才会依次向其它的注册中心注册,总共重试3次,如果3个service-url都没有注册成功,则注册失败。每隔一个心跳时间,会再次尝试。
    所以说,为了保证服务注册到同一个zone的注册中心,一定要注意availability-zones的顺序,必须把同一zone写在前面

3.4.2 服务调用的配置文件

eureka:
  instance:
    metadata-map:
      zone: zone-1

服务消费者和服务提供者分别属于哪个zone,均是通过eureka.instance.metadata-map.zone来判定的。
服务消费者会先通过ribbon去注册中心拉取一份服务提供者的列表,然后通过eureka.instance.metadata-map.zone指定的zone进行过滤,过滤之后如果同一个zone内的服务提供者有多个实例,则会轮流调用。
只有在同一个zone内的所有服务提供者都不可用时,才会调用其它zone内的服务提供者。

3.4.3 扩展

eureka.instance.lease-renewal-interval-in-seconds: 30

服务和注册中心的心跳间隔时间,默认为30s

eureka.instance.lease-expiration-duration-in-seconds: 90

服务和注册中心的心跳超时时间,默认为90s。也就是说,当一个服务异常down掉后,90s之后注册中心才会知道这个服务不可用了。在此期间,依旧会把这个服务当成正常服务。ribbon调用仍会把请求转发到这个服务上。为了避免这段期间出现无法提供服务的情况,要开启ribbon的重试功能,去进行其它服务提供者的重试。

4 手工改变eureka注册中心的服务状态

1.删除服务
通过eureka注册中心的注册的服务,可以通过DELETE来删除指定的服务,发送地址为:
http:// s e r v e r : {server}: server:{port}/eureka/apps/ s e r v i c e N a m e / {serviceName}/ serviceName/{instanceId}
例子:erueka注册中心: 10.100.1.100, 端口: 5671
服务名: TEST-SERVER
服务实例id: 192.168.10.54:8883
向下面的url通过http发送 DELETE 命令,则可以删除整个服务
http://10.100.1.100:5671/eureka/apps/TEST-SERVER/192.168.10.54:8883
值得注意的是,Eureka客户端每隔一段时间(默认30秒)会发送一次心跳到注册中心续约。如果通过这种方式下线了一个服务,而没有及时停掉的话,该服务很快又会回到服务列表中。所以,可以先停掉服务,再发送请求将其从列表中移除。

2.改变服务状态
HTTP发 PUT命令,格式如下
http:// s e r v e r : {server}: server:{port}/eureka/apps/ s e r v i c e N a m e / {serviceName}/ serviceName/{instanceId}/status?value= v a l u e 其中 {value} 其中 value其中{value}的选择如下的值之一。
OUT_OF_SERVICE
DOWN
UP

5 eureka集群在服务调用中的作用

整个Eureka的过程如下:

1.先启动Eureka注册中心
2.启动服务提供者服务
3.服务提供者服务将自身信息(比如服务地址)以别名方式注册到Eureka注册中心
4.消费者服务在需要调用接口时,使用服务别名到注册中心获取实际的RPC远程调用地址
5.消费者获得调用地址后,底层实际是利用 HttpClient 技术实现远程调用
6.消费者获得服务地址后会缓存至本地JVM内存中,默认每间隔30秒更新一次服务调用地址

6 Eureka自我保护(CAP里面的AP分支)

1.自我保护机制
保护模式主要用于一组客户端和EurekaServer之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

如果在Eureka Server的首页看到以下提示,说明Eureka进入了保护模式(上面2. 单机Eureka构建步骤中提到过):

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

换句话说就是,某时刻某一个微服务不可用了,Eureka不会立刻清理,而是依旧会对该微服务的信息进行保存。

2.产生原因
为什么会产生Eureka自我保护机制???

EurekaClient与EurekaServer网络不通情况下,为了保证 EurekaClient可以正常运行,EurekaServer不会立刻将EurekaClient服务剔除。

什么是自我保护模式?

默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之前无法正常通信,以上行为可能变得非常危险——因为微服务本身是健康的,只是由于网络问题链接不到EurekaServer,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障,网络延时),那么这个节点就会进入自我保护模式。

在自我保护模式中,EurekaServer会保护服务注册表中的信息,不再注销任何服务实例,宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

自我保护模式阈值计算:

每个instance的预期心跳数目 = 60/每个instance的心跳间隔秒数
阈值 = 所有注册到服务的instance的数量的预期心跳之和 *自我保护系数

以上的参数都可配置的:

instance的心跳间隔秒数:eureka.instance.lease-renewal-interval-in-seconds
自我保护系数:eureka.server.renewal-percent-threshold
如果我们的实例比较少且是内部网络时,推荐关掉此选项。我们也可以通过eureka.server.enable-self-preservation = false来禁用自我保护系数

7 新的Eureka Server节点加入集群后的影响

当有新的节点加入到集群中,会对现在Eureka Server和Eureka Client有什么影响以及他们如何发现新增的Eureka Server节点:

新增的Eureka Server:在Eureka Server重启或新的Eureka Server节点加进来的,它会从集群里其它节点获取所有的实例注册信息。如果获取同步失败,它会在一定时间(此值由决定eureka.server.peer-eureka-nodes-update-interval-ms决定)内拒绝服务。
已有Eureka Server和Service Consumer如何发现新的Eureka Server

已有的Eureka Server:在运行过程中,Eureka Server之间会定时同步实例的注册信息。这样即使新的Application Service只向集群中一台注册服务,则经过一段时间会集群中所有的Eureka Server都会有这个实例的信息。那么Eureka Server节点之间如何相互发现,各个节点之间定时(时间由eureka.server.peer-eureka-nodes-update-interval-ms决定)更新节点信息,进行相互发现。
Service Consumer:Service Consumer刚启动时,它会从配置文件读取Eureka Server的地址信息。当集群中新增一个Eureka Server中时,那么Service Provider如何发现这个Eureka Server?Service Consumer会定时(此值由eureka.client.eureka-service-url-poll-interval-seconds决定)调用Eureka Server集群接口,获取所有的Eureka Server信息的并更新本地配置。

8 新服务注册(Register)注册时的影响

Service Provider要对外提供服务,把自己注册到Eureka Server上。如果配置参数eureka.client.registerWithEureka=true(默认值true)时,会向Eureka Server注册进行注册,Eureka Server会保存注册信息到内存中。

Service Consumer为了避免每次调用服务请求都需要向Eureka Server获取服务实例的注册信息,此时需要设置eureka.client.fetchRegistry=true,它会在本地缓存所有实例注册信息。为了保证缓存数据的有效性,它会定时(值由eureka.client.registry-fetch-interval-seconds定义,默认值为30s)向注册中心更新实例。

9 服务下线和剔除

服务的下线有两种情况:

1.在Service Provider服务shutdown的时候,主动通知Eureka Server把自己剔除,从而避免客户端调用已经下线的服务。
2.Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默认值为0,默认情况不删除实例)进行检查,如果发现实例在在一定时间(此值由eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s)内没有收到心跳,则会注销此实例。

这种情况下,Eureka Client的最多需要[eureka.instance.lease-renewal-interval-in-seconds + eureka.client.registry-fetch-interval-seconds]时间才发现服务已经下线。同理,一个新的服务上线后,Eureka Client的服务消费方最多需要相同的时间才发现服务已经上线

服务下线,同时会更新到Eureka Server其他节点和Eureka client的缓存,流程类似register过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值