极客时间已完结课程限时免费阅读

17 | 如何识别服务节点是否存活?

17 | 如何识别服务节点是否存活?-极客时间

17 | 如何识别服务节点是否存活?

讲述:胡忠想

时长08:13大小3.76M

今天我要与你分享如何识别服务节点是否存活,这在服务治理中是十分重要的。在进入正题之前,你可以先复习一下专栏第 5 期,我在讲解注册中心原理的时候,以开源注册中心 ZooKeeper 为例,描述了它是如何管理注册到注册中心的节点的存活的。
其实 ZooKeeper 判断注册中心节点存活的机制其实就是注册中心摘除机制,服务消费者以注册中心中的数据为准,当服务端节点有变更时,注册中心就会把变更通知给服务消费者,服务消费者就会调用注册中心来拉取最新的节点信息。
这种机制在大部分情况下都可以工作得很好,但是在网络频繁抖动时,服务提供者向注册中心汇报心跳信息可能会失败,如果在规定的时间内,注册中心都没有收到服务提供者的心跳信息,就会把这个节点从可用节点列表中移除。更糟糕的是,在服务池拥有上百个节点的的时候,每个节点都可能会被移除,导致注册中心可用节点的状态一直在变化,这个时候应该如何处理呢?
下面就结合我在实践中的经验,给你讲解几种解决方案。

心跳开关保护机制

在网络频繁抖动的情况下,注册中心中可用的节点会不断变化,这时候服务消费者会频繁收到服务提供者节点变更的信息,于是就不断地请求注册中心来拉取最新的可用服务节点信息。当有成百上千个服务消费者,同时请求注册中心获取最新的服务提供者的节点信息时,可能会把注册中心的带宽给占满,尤其是注册中心是百兆网卡的情况下。
所以针对这种情况,需要一种保护机制,即使在网络频繁抖动的时候,服务消费者也不至于同时去请求注册中心获取最新的服务节点信息
我曾经就遇到过这种情况,一个可行的解决方案就是给注册中心设置一个开关,当开关打开时,即使网络频繁抖动,注册中心也不会通知所有的服务消费者有服务节点信息变更,比如只给 10% 的服务消费者返回变更,这样的话就能将注册中心的请求量减少到原来的 1/10。
当然打开这个开关也是有一定代价的,它会导致服务消费者感知最新的服务节点信息延迟,原先可能在 10s 内就能感知到服务提供者节点信息的变更,现在可能会延迟到几分钟,所以在网络正常的情况下,开关并不适合打开;可以作为一个紧急措施,在网络频繁抖动的时候,才打开这个开关。

服务节点摘除保护机制

服务提供者在进程启动时,会注册服务到注册中心,并每隔一段时间,汇报心跳给注册中心,以标识自己的存活状态。如果隔了一段固定时间后,服务提供者仍然没有汇报心跳给注册中心,注册中心就会认为该节点已经处于“dead”状态,于是从服务的可用节点信息中移除出去。
如果遇到网络问题,大批服务提供者节点汇报给注册中心的心跳信息都可能会传达失败,注册中心就会把它们都从可用节点列表中移除出去,造成剩下的可用节点难以承受所有的调用,引起“雪崩”。但是这种情况下,可能大部分服务提供者节点是可用的,仅仅因为网络原因无法汇报心跳给注册中心就被“无情”的摘除了。
这个时候就需要根据实际业务的情况,设定一个阈值比例,即使遇到刚才说的这种情况,注册中心也不能摘除超过这个阈值比例的节点
这个阈值比例可以根据实际业务的冗余度来确定,我通常会把这个比例设定在 20%,就是说注册中心不能摘除超过 20% 的节点。因为大部分情况下,节点的变化不会这么频繁,只有在网络抖动或者业务明确要下线大批量节点的情况下才有可能发生。而业务明确要下线大批量节点的情况是可以预知的,这种情况下可以关闭阈值保护;而正常情况下,应该打开阈值保护,以防止网络抖动时,大批量可用的服务节点被摘除。
讲到这里,我们先小结一下。
心跳开关保护机制,是为了防止服务提供者节点频繁变更导致的服务消费者同时去注册中心获取最新服务节点信息;服务节点摘除保护机制,是为了防止服务提供者节点被大量摘除引起服务消费者可以调用的节点不足。
可见,无论是心跳开关保护机制还是服务节点摘除保护机制,都是因为注册中心里的节点信息是随时可能发生变化的,所以也可以把注册中心叫作动态注册中心。
那么是不是可以换个思路,服务消费者并不严格以注册中心中的服务节点信息为准,而是更多的以服务消费者实际调用信息来判断服务提供者节点是否可用。这就是下面我要讲的静态注册中心。

静态注册中心

前面讲过心跳机制能保证在服务提供者出现异常时,注册中心可以及时把不可用的服务提供者从可用节点列表中移除出去,正常情况下这是个很好的机制。
但是仔细思考一下,为什么不把这种心跳机制直接用在服务消费者端呢?
因为服务提供者是向服务消费者提供服务的,是否可用服务消费者应该比注册中心更清楚,因此可以直接在服务消费者端根据调用服务提供者是否成功来判定服务提供者是否可用。如果服务消费者调用某一个服务提供者节点连续失败超过一定次数,可以在本地内存中将这个节点标记为不可用。并且每隔一段固定时间,服务消费者都要向标记为不可用的节点发起保活探测,如果探测成功了,就将标记为不可用的节点再恢复为可用状态,重新发起调用。
这样的话,服务提供者节点就不需要向注册中心汇报心跳信息,注册中心中的服务节点信息也不会动态变化,也可以称之为静态注册中心。
从我的实践经历来看,一开始采用了动态注册中心,后来考虑到网络的复杂性,心跳机制不一定是可靠的,而后开始改为采用服务消费者端的保活机制,事实证明这种机制足以应对网络频繁抖动等复杂的场景。
当然静态注册中心中的服务节点信息并不是一直不变,当在业务上线或者运维人工增加或者删除服务节点这种预先感知的情况下,还是有必要去修改注册中心中的服务节点信息。
比如在业务上线过程中,需要把正在部署的服务节点从注册中心中移除,等到服务部署完毕,完全可用的时候,再加入到注册中心。还有就是在业务新增或者下线服务节点的时候,需要调用注册中心提供的接口,添加节点信息或者删除节点。这个时候静态注册中心有点退化到配置中心的意思,只不过这个时候配置中心里存储的不是某一项配置,而是某个服务的可用节点信息。

总结

今天我给你讲解了动态注册中心在实际线上业务运行时,如果遇到网络不可靠等因素,可能会带来的两个问题,一个是服务消费者同时并发访问注册中心获取最新服务信息导致注册中心带宽被打满;另一个是服务提供者节点被大量摘除导致服务消费者没有足够的节点可以调用。
这两个问题都是我在业务实践过程中遇到过的,我给出的两个解决方案:心跳开关保护机制和服务节点摘除保护机制都是在实践中应用过的,并且被证明是行之有效的。
而静态注册中心的思路,是在斟酌注册中心的本质之后,引入的另外一个解决方案,相比于动态注册中心更加简单,并且基于服务消费者本身调用来判断服务节点是否可用,更加直接也更加准确,尤其在注册中心或者网络出现问题的时候,这种方案基本不受影响。

思考题

在实际的微服务架构中,注册中心主动心跳机制和客户端摘除机制可能会同时使用,比如 Spring Cloud 就把这两种机制结合起来识别服务节点是否存活。如果注册中心没有收到某一个服务节点的心跳汇报,而服务消费者又调用这个服务节点成功了,你认为应该以哪个为准?为什么?
欢迎你在留言区写下自己的思考,与我一起讨论。
分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 2

提建议

上一篇
16 | 如何搭建一套适合你的服务追踪系统?
下一篇
18 | 如何使用负载均衡算法?
unpreview
 写留言

精选留言(20)

  • oddrock
    2018-09-29
    应该以客服端为准,谁使用谁有发言权。 我觉得注册中心的主动心跳探测不应作为客户端摘除不可用服务端节点的依据,而是要作为参考值,比如将这种探测信息发给客户端,客户端在负载均衡时,将这种疑似问题节点降权重或作为备用节点,这样是不是比较好
    共 1 条评论
    36
  • xiaoxi666
    2018-09-29
    相对于动态注册,静态注册的方式把探测任务分散到了服务消费者,在增加服务消费者工作量的同时,再考虑一个问题:如果某个服务被多个消费者调用,那么该服务提供者会收到大量探测请求,但这是不必要的。所以我认为被大量业务依赖的公共的服务提供方应尽可能采用动态注册的方式。敬请指正。
    共 2 条评论
    18
  • feimeng0532
    2018-09-29
    开关或者保护,怎么检测到网络抖动?
    共 1 条评论
    10
  • pscj
    2018-11-16
    感觉静态注册中心就完全去中心化了,没有中心的概念了,每个peer自己判断节点的死活,自己维护一套状态表,是这个意思吧?

    作者回复: 对,这个时候注册中心类似一个配置中心了

    共 2 条评论
    6
  • 王鸿运
    2019-01-14
    对于注册中心网络抖动问题,能否通过下面两种方法解决: 1.服务提供方定时上报心跳,注册中心进行ack确认,并且在ack中告知下次上报的时间间隔(该时间间隔为注册中心剔除节点最大不活跃时间的一半),如果服务提供方在超时时间后未收到ack,采用指数补偿策略进行重试上报n次(比如n=3),这种重试的方式,有可能在网络抖动情况下,因此重试包网络风暴 2.双向探测,注册中心在节点达到剔除时间时,不直接剔除,而是进行主动探测n次(比如n等于3),探测几次还是失败,才剔除,然后通知订阅方更新
    展开
    共 1 条评论
    4
  • null
    2018-09-29
    动态注册中心: “心跳开关保护机制”这种机制为了保护注册中心不被挤爆,但对服务消费者不太友善,也有可能会发生大面积消费者请求服务提供者失败的情况。当有 session_timeout 服务提供者节点被摘除时,只通知 10% 的服务消费者。 问题一:是每次随机取 10%,还是之前已通知的服务消费者就不再通知了? 问题二:如何监控判断网络是否频繁抖动,并且如何打开这个开关? 静态注册中心: 控制权反转,由服务消费者维护服务提供者的存活状态,服务提供者节点不再向注册中心汇报心跳信息。 注册中心不再维护服务提供者节点的心跳信息,只有消费者节点首次启动时,从注册中心拉取服务提供者节点信息,而后续便不再获取注册中心的提供者节点信息。即使消费者节点定时获取提供者节点信息,因为注册中心不维护提供者的心路信息,所以这些数据也是不可用的。 问题三:当有新的节点加入注册中心,或者需要从注册中心下线部分节点,服务消费者如何感知? 谢谢古月老师!爱你么么哒~
    展开
    共 1 条评论
    2
  • 松花皮蛋me
    2019-02-17
    我们公司是考虑动静结合的,这样添加节点也能主动推送给客户端
    1
  • echo_陈
    2018-09-29
    如果使用静态注册中心,虽然很好的解决了网络波动问题,那新增服务节点……还需要人工更新配置,感觉不是很自动化啊。如果是动态注册中心,启动的节点会自动接入集群里,免配置,更方便……唉,要是动态配置中心能根据请求行为自动探测出网络问题做一些决策就好了哈哈,我想多了
    1
  • 拉欧
    2018-09-29
    当然要以服务消费端为准,服务消费者才是真实的调用方
    1
  • 俯瞰风景.
    2021-10-08
    注册中心是服务于远程调用的,在服务提供者和服务消费者之间建立正确的连接。 心跳开关保护机制:当网络连接出现抖动时,在注册中心摘除机制之下,注册中心会频繁更新服务提供者信息,导致服务消费者频繁请求注册中心获得最新的信息,造成网络带宽被打满,这种情况要设置一个开关,只通知一部分服务消费者进行服务信息变更,减少带宽压力。 服务节点摘除保护机制:在网络频繁抖动时,注册中心大量“误判”下线服务节点,造成服务节点不够用。这种情况要设置一个阀值,不允许下线超过指定阀值的节点。 静态注册中心:注册中心动态更新服务节点的方式被称作动态注册中心,与之相对的是静态注册中心。通过服务消费者自己去判断服务节点是否下线,这种方式准确率更高。在这种方式下,注册中心就变成了配置中心。
    展开
  • J.Smile
    2020-11-11
    应该不是叫“”心跳开关保护机制吧?我觉得应该是变更通知保护开关才对,毕竟是不让注册中心通知过多的客户端嘛!
  • Geek_6ea8f7
    2020-01-04
    注册中心心跳检测和客户端摘除在主流的开源框架中是如何选择的? 这些框架中是否包含心跳开关保护和摘除保护的支持? 如果支持怎样修改配置?如果不支持要如何二次开发实现? 同时使用注册中心摘除和客户端摘除,二者信息不一致时,权衡的方案又该如何设计?
  • 满力
    2019-07-13
    你好老师!我记得服务提供者不可用了,是zk主动推送给消费端的吧,你这里说的是消费端主动去拉取
    共 1 条评论
  • 2019-06-15
    如果华夏村的村委会告诉张三李四去世了,但是张三去李四家拿东西又碰见了李四。 那么问题来了,李四到底死没死?张三开始了思考。
    共 1 条评论
  • 六维
    2019-05-29
    应该以服务消费者的为准,做为服务消费者调用成功了,说明服务提供者是可以提供服务的。注册中心未收到心跳汇报,可能是与注册中心的网络连通性的问题,并不意味着服务提供者不可提供服务。
  • 亚林
    2019-05-29
    以【服务消费者又调用这个服务节点成功】为准,因为服务提供者与注册中心之间通信不佳,可能是网络原因导致的。
  • 东风微鸣
    2018-11-17
    你好,我们目前在上的新系统,使用的spring cloud微服务架构,目前刚刚计划改为eureka主动探测机制,目前没听过有设置保护机制,那么如果网络真出问题了,是不是很有可能出现您说的那个注册中心网络占满的问题?

    作者回复: 是的,我记得spring cloud也是有类似的摘除保护机制的

  • yan
    2018-10-18
    只通知10%的用户,那么另外的90%的用户是让他们失败吗?还是后续会再次通知,只是分批次,每次通知10%,知道全部通知完毕?

    作者回复: 因为客户端会隔一段时间来请求,这一次请求没有变化,下一次请求可能就有变化了

    共 2 条评论
  • 波波安
    2018-10-14
    老师,有个疑问,如果采用静态注册中心,那服务超时时间,重试次数这些服务配置信息的改变怎么及时通知到消费端呢?
  • 冬末未末
    2018-09-29
    静态注册中心添加节点怎么自动推送给客户端呢?