Spring Cloud Eureka 深入理解

1 Eureka设计理念

作为一个服务注册及发现中心,主要解决如下几个问题:

  • 服务实例如何注册到服务中心
  • 服务实例如何从服务中心剔除
  • 服务实例信息的一致性问题

下面我们来一一介绍Eureka每个环境的实现原理:

  • Register——服务注册

当Eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,在Eureka服务器会维护一个已注册的服务列表。注册服务列表使用一个嵌套HashMap保存信息,数据结构如下:

HashMap的第一层为应用名称和对应的服务实例。

HashMap的第二层为服务实例及其对应的注册信息,包括IP地址、端口、运行状况指标的Url、主页地址等信息。

  • Renew——服务续约

Eureka Client在默认的情况下会每隔30秒发送一次心跳来进行服务续约。通过服务续约来告知Eureka Server该Eureka Client仍然可用,没有出现故障。在正常情况下,如果Eureka Server在90秒内没有收到Eureka Client的心跳,也就是连续3次没有收到客户端的心跳,Eureka Server会将Eureka Client实例从注册列表中删除。注意:官网建议不要更改服务续约的间隔时间。

  • Fetch Registries——获取服务注册列表信息

Eureka Client从Eureka Server获取服务注册表信息,并将其缓存在本地。Eureka Client会使用服务注册列表信息查找其他服务的信息,从而进行远程调用。该注册列表信息定时(每30秒)更新一次,每次返回注册列表信息可能与Eureka Client的缓存信息不同,Eureka Client会自己处理这些信息。如果某种原因导致注册列表信息不能及时匹配,Eureka Client会重新获取整个注册表信息。Eureka Server缓存了所有的服务注册列表信息,并将整个注册列表以及每个应用程序的信息压缩,压缩内容和没有压缩的内容完全相同。Eureka Client和Eureka Server可以使用JSON 和XML数据格式进行通信。在默认的情况下,Eureka Client使用JSON格式的方式来获取服务注册列表的信息。

  • Cancel——服务下线

Eureka Client在程序关闭时可以向Eureka Server发送下线请求。发送请求后,该客户端的实例信息将从Eureka Server的服务注册列表中删除。

  • Eviction——服务剔除

在默认情况下,当Eureka Client连续90秒没有向Eureka Server发送服务续约(即心跳)时,Eureka Server会将该服务实例从服务注册列表删除,即服务剔除。

下面通过一张图,梳理一下Eureka的整个工作流程。

2 Eureka自我保护模式

在分布式系统领域有个CAP定理(CAP theorem),又被称为布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下3点。

  • 一致性(Consistency):同一个数据在集群中的所有节点,同一时刻是否都是同样的值。
  • 可用性(Availability):集群中一部分节点故障后,集群整体是否还能处理客户端的请求。
  • 分区容忍性(Partition tolerance):是否允许数据的分区,数据分区的意思是指是否允许集群中的节点之间无法通信。

这3个特性在任何分布式系统中都不可能同时满足,最多同时满足其中两个。

Eureka设计哲学采用的是AP原则,也就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。因此,在Eureka中有一个自我保护模式,并默认开启。在自我保护模式下,Eureka服务器会保护服务注册表中的信息,不再注销任何服务实例。

Eureka服务器自我保护模式开启的条件是:当Eureka服务器每分钟收到心跳续租的数量低于一个阈值,就会触发自我保护模式。当它收到的心跳数重新恢复到阈值以上时,该Eureka服务器节点才会自动退出自我保护模式。心跳阀值计算公式如下:
服务实例总数量×(60/每个实例心跳间隔秒数)×自我保护系数(0.85)

可以通过将eureka.server.enable-self-preservation属性的值设置为false来禁用该模式。

3 获取服务实例的时间

在实际进行微服务架构开发过程中,经常会遇到一个服务实例上线后需要很长一段时间才能够被其他服务调用者获取和使用,并不能在微服务一上线就立即被获取到,这是Eureka的机制造成的。在Eureak服务治理环境下,一个微服务上线有三处缓存处理和一处延迟处理,经过这些处理后才能够被服务消费方获取到并使用,它们分别是:

  • Eureka Client的注册延迟

Eureka Client启动之后,不是立即向Eureka Server注册的,而是有一个延迟向服务端注册的时间。

  • Eureka Server的响应缓存

Eureka Server维护每 30 秒更新一次响应缓存,可通过更改配置eureka.server.responseCache UpdateIntervalMs来修改。所以即使是刚刚注册的实例,也不会立即出现在服务注册列表中。

  • Eureka Client的缓存

Eureka Client保留注册表信息的缓存。该缓存每30秒更新一次(如前所述)。因此,Eureka Client刷新本地缓存并发现其他新注册的实例可能需要30秒。

  • LoadBalancer的缓存

Ribbon负载均衡会从Eureka客户端获取服务列表,并将负载均衡后的结果缓存30秒,所以对于Eureka客户端新同步过来的服务节点,可能也会需要30秒之后才能被负载均衡使用。

综上几个因素,一个新的服务实例,即使能够很快启动的实例,也不能马上被Eureka服务器发现,其他服务消费者需要一段时间,最长可能需要2分钟以上,才能够被发现和使用。

4 码农来洞见

本文主要从Eureka设计理念及实现原理介绍了Eureka内部运行的整个生命周期。了解原理知识对我们解决现实问题提供了很好的思路。有病尽量不要乱投医,还是要对症下药。

猜你喜欢

转载自blog.csdn.net/pangpengshuai/article/details/119967133
今日推荐