【SpringCloud】 服务注册与发现 Eureka 工作原理

 Eureka是Netflix开源的一款提供服务注册和发现的产品

  • github地址为 https://github.com/Netflix/eureka
  • 注册中心是分布式开发的核心组件之一,而eureka是spring cloud推荐的注册中心实现,因此对于Java开发同学来说,还是有必要学习eureka的,特别是其架构及设计思想。

官方文档定义是:Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. We call this service, the Eureka Server. Eureka also comes with a Java-based client component,the Eureka Client, which makes interactions with the service much easier. The client also has a built-in load balancer that does basic round-robin load balancing.
Eureka是一个REST (Representational State Transfer)服务,它主要用于AWS云,用于定位服务,以实现中间层服务器的负载平衡和故障转移,我们称此服务为Eureka服务器。Eureka也有一个基于java的客户端组件,Eureka客户端,这使得与服务的交互更加容易,同时客户端也有一个内置的负载平衡器,它执行基本的循环负载均衡。

Eureka提供了完整的(服务注册)Service Registry和(服务发现)Service Discovery实现,并且也经受住了Netflix自己的生产环境考验,相对使用起来会比较省心(同时Spring Cloud还有一套非常完善的开源代码来整合Eureka,所以使用起来非常方便)

本章的目标:

  1. eureka基础概念及架构
  2. 服务发现原理
  3. eureka server/client流程分析及优缺点分析
  4. 关于eureka(结合spring cloud)的使用, 可以看下 程序猿DD 关于spring cloud的相关教程

一、Eureka 基础

    Eureka 架构图

             

  • Eureka Server:提供服务注册和发现,多个Eureka Server之间会同步数据,做到状态一致(分区可用性)(AP)
  • Service Provider:服务提供方,将自身服务注册到Eureka,从而使服务消费方能够找到
  • Service Consumer:服务消费方,从Eureka获取注册服务列表,从而能够消费服务

注意,上图中的3个角色都是逻辑角色,在实际运行中,这几个角色甚至可以是同一个项目(JVM进程)中。

(1)Eureka 核心概念

     服务提供者和服务的消费者,本质上也是 Eureka Client 角色。整体上可以分为两个主体:

  • Eureka Server (注册中心服务端)
  • Eureka Client(注册中心客户端)

Eureka Server:注册中心服务端 主要对外提供了三个功能:

  1. 服务注册 :服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表
  2. 提供注册表:服务消费者在调用服务时,如果Eureka Client 没有缓存注册表的话,会从Eureka Server 获取最新的注册表
  3. 同步状态:Eureka Client 通过注册,心跳机制和Eureka Server 同步当前客户端的状态。

Eureka Client:注册中心客户端:Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。

  1. Register: 服务注册 :服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
  2. Renew: 服务续约:Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除,此时间可配置,一般情况不建议更改。

   服务续约的两个重要属性

服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-renewal-interval-in-seconds=30

服务失效的时间,默认为90秒。
eureka.instance.lease-expiration-duration-in-seconds=90

    3. Eviction 服务剔除 :当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。

    4. Cancel: 服务下线:Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:

DiscoveryManager.getInstance().shutdownComponent();

   5. GetRegisty: 获取注册列表信息:Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。

如果由于某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。

获取服务是服务消费者的基础,所以必有两个重要参数需要注意:

# 启用服务消费者从注册中心拉取服务列表的功能
eureka.client.fetch-registry=true

# 设置服务消费者从注册中心拉取服务列表的间隔
eureka.client.registry-fetch-interval-seconds=30

  6. Remote Call: 远程调用:当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。

(2)自我保护机制

默认情况下,如果Eureka Server 在一定的90s内没有接收到某个微服务实例的心跳,会注销(剔除)该实例,但是在微服务架构下服务之间通常都是跨进程调用,网络通信往往会面临各种问题,比如微服务状态正常,网络分区故障,导致此实例被踢出。

固定时间内大量的实例被剔除,可能会严重威胁整个微服务架构的可用性。为了解决这个问题,Eureka 开启了自我保护机制,自我保护机制触发时机:Eureka Server 在运行期间会统计心跳失败比例在15分钟之内是否低于85%,如果低于85%,Eureka Server 即会进入自我保护机制。

自我保护机制主要在Eureka Client和Eureka Server之间存在网络分区的情况下发挥保护作用,在服务器端和客户端都有对应实现。假设在某种特定的情况下(如网络故障), Eureka Client和Eureka Server无法进行通信,此时Eureka Client无法向Eureka Server发起注册和续约请求,Eureka Server中就可能因注册表中的服务实例租约出现大量过期而面临被剔除的危险,然而此时的Eureka Client可能是处于健康状态的(可接受服务访问),如果直接将注册表中大量过期的服务实例租约剔除显然是不合理的,自我保护机制提高了eureka的服务可用性。

当自我保护机制触发时,Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务,仍能查询服务信息并且接受新服务注册请求,也就是其他功能是正常的。这里思考下,如果eureka节点A触发自我保护机制过程中,有新服务注册了然后网络回复后,其他peer节点能收到A节点的新服务信息,数据同步到peer过程中是有网络异常重试的,也就是说,是能保证最终一致性的。

Eureka Server 触发自我保护机制后,页面会出现提示:

å¨è¿éæå¥å¾çæè¿°

Eureka Server 进入自我保护机制,会出现以下几种情况:

  1. Eureka server 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
  2. Eureka server 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
  3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

Eureka 自我保护机制是为了防止误杀服务而提供的一个机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除掉客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。

如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,即会调用失败。对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。

通过在 Eureka Server 配置如下参数,开启或者关闭保护机制,生产环境建议打开:

eureka.server.enable-self-preservation=true

二、Eureka 集群原理

再来看看 Eureka 集群的工作原理。我们假设有三台 Eureka Server 组成的集群,第一台 Eureka Server 在北京机房,另外两台 Eureka Server 在深圳和西安机房。这样三台 Eureka Server 就组建成了一个跨区域的高可用集群,只要三个地方的任意一个机房不出现问题,都不会影响整个架构的稳定性。

        å¨è¿éæå¥å¾çæè¿°

从图中可以看出 Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。

从图中可以看出 Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。

如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点。当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行节点间复制,将请求复制到其它 Eureka Server 当前所知的所有节点中。

Eureka Server 集群之间的状态是采用异步方式同步的,所以不保证节点间的状态一定是一致的,不过基本能保证最终状态是一致的。

(1)Eureka 分区

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

  •   region:可以理解为地理上的不同区域,比如亚洲地区,中国区或者深圳等等。没有具体大小的限制。根据项目具体的情况,可以自行合理划分 region。
  • zone:可以简单理解为 region 内的具体机房,比如说 region 划分为深圳,然后深圳有两个机房,就可以在此 region 之下划分出 zone1、zone2 两个 zone。

上图中的 us-east-1c、us-east-1d、us-east-1e 就代表了不同的 Zone。Zone 内的 Eureka Client 优先和 Zone 内的 Eureka Server 进行心跳同步,同样调用端优先在 Zone 内的 Eureka Server 获取服务列表,当 Zone 内的 Eureka Server 挂掉之后,才会从别的 Zone 中获取信息。

(2)Eurka 保证 AP

Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。

(3)Eurka 工作流程

    了解完 Eureka 核心概念,自我保护机制,以及集群内的工作原理后,我们来整体梳理一下 Eureka 的工作流程:

  1. Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息
  2. Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
  3. Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常
  4. 当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
  5. 单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
  6. 当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
  7. Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
  8. 服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
  9. Eureka Client 获取到目标服务器信息,发起服务调用
  10. Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除

三、小总结

 为什么要用Eureka 呢,因为分布式开发中,任何单点的服务都不能保证不会中断,因此需要服务发现机制,某个节点中断后,服务消费者能及时感知到保证服务高可用。从Eureka的设计与实现上来说还是容易理解的,Spring Cloud 将它集成在自己的子项目 Spring cloud netflix中,实现Spring Cloud 的服务发现功能。

注册中心除了用eureka之外,还有zookeeper、consul、nacos等解决方案,他们实现原理不同,可按需使用

(1)Eureka比ZooKeeper相比优势

  • Zookeeper保证CP: 

 ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它 很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。

        在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个 CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就 是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的 职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性 的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且, 作为ZooKeeper的核心实现算法Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。   

        当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
 

  • Eureka保证AP: 

 在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务 注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。

          Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。

(2)eureka不足:

eureka consumer本身有缓存,服务状态更新滞后,最常见的状况就是,服务下线了但是服务消费者还未及时感知,此时调用到已下线服务会导致请求失败,只能依靠consumer端的容错机制来保证。

Eureka 为了保障注册中心的高可用性,容忍了数据的非强一致性,服务节点间的数据可能不一致, Client-Server 间的数据可能不一致。比较适合跨越多机房、对注册中心服务可用性要求较高的使用场景。

相关文章

  1. Eureka 原理分析
  2. Eureka 工作原理

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

试剑江湖。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值