那你首先,了解注册中心摘除机制吗?
就是【服务Consumer】以【注册中心】中的数据为准,当服务端节点有变更时,【注册中心】会把变更通知给【服务Consumer】,【服务Consumer】就调用【注册中心】拉取最新的节点信息。
是的,其实这种机制一般也够用了,但当网络频繁抖动时,【服务Provider】向【注册中心】汇报心跳信息可能失败。若在规定时间内,【注册中心】都未收到【服务Provider】的心跳信息,就会把该节点从可用节点列表中移除。
更糟的是,在服务池拥有上百个节点时,每个节点都可能会被移除,导致【注册中心】可用节点的状态一直在变化,这该如何解决?
可以考虑心跳开关保护机制。
在网络频繁抖动时,【注册中心】的可用节点不断变化,这时【服务Consumer】会频繁收【服务Provider】节点变更信息,于是不断请求【注册中心】。 当很多【服务Consumer】同时请求【注册中心】获取最新【服务Provider】节点信息时,很容易把【注册中心】带宽打满。
所以需要一种措施,保证即使在网络频繁抖动时,【服务Consumer】也不会 同时 请求【注册中心】。
这就是给【注册中心】设置一个开关。 当开关打开时,即使网络频繁抖动,【注册中心】也不会通知所有【服务Consumer】,比如只通知10%的【服务Consumer】,这就能降低注册中心需要处理的请求量压力。
那这种方案有什么问题吗?
技术都是有利有弊的,开关的代价就是会导致【服务Consumer】感知最新服务节点信息延迟。所以应该作为一个紧急措施,在网络频繁抖动时,才打开开关。
综上,该机制是为避免【服务Provider】节点频繁变更,而导致【服务Consumer】同时请求【注册中心】。
那还有别的方案吗?
是的,还有服务节点摘除保护机制。 【服务Provider】在进程启动时,会注册服务到【注册中心】,并每隔一段时间,汇报心跳给【注册中心】,通知自己的存活状态。 若隔了一段固定时间后,【服务Provider】仍没有汇报心跳给【注册中心】,【注册中心】就会认为该节点已死,将其从可用节点中移除。
若遇到网络问题,大批【服务Provider】节点汇报给【注册中心】的心跳信息都可能会传达失败,【注册中心】就会把它们都从可用节点列表中移除,造成剩下可用节点难以承受所有调用,引起“雪崩”。但这种情况下,可能大部分服务提供者节点是可用的,仅因为网络原因无法汇报心跳给注册中心就被“无情”摘除。
这就需要根据实际业务,设定一个阈值比例,即使网络抖动,【注册中心】也不能摘除超过这个阈值比例的节点。通常设定在20%。因为绝大部分时间,节点变化也不会变化频繁,只有在如下情况才可能发生:
- 业务明确要下线大批节点 这种情况又是可预知的,所以可以关闭阈值保护。
- 网络抖动 一般正常时,应打开阈值保护,以防网络抖动时,大批量可用服务节点被摘除。
综上,该机制是为避免【服务Provider】节点被大量摘除,而导致【服务Consumer】可调用节点不足。
所以这两种机制,都是因为【注册中心】的节点信息瞬息万变,所以也经常把【注册中心】称为【动态注册中心】。
我开始疑惑了,那是否能另辟蹊径,【服务Consumer】并不严格以【注册中心】中的服务节点信息为准,而是更多的以【服务Consumer】实际调用信息来判断【服务Provider】是否可用呢?
有的,这就是静态注册中心。 心跳机制能保证在【服务Provider】出现异常时,【注册中心】可以及时把不可用的【服务Provider】从可用节点列表中移除,这很好。 但仔细思考,为何不把这种心跳机制直接用在【服务Consumer】?
因为【服务Provider】是向【服务Consumer】提供服务,是否可用【服务Consumer】应该比【注册中心】更清楚,因此可直接在【服务消费者】端根据调用【服务Provider】是否成功,以判定服务Provider】是否可用。 若【服务Consumer】调用某一【服务Provider】连续失败超过一定次数,可在本地内存将该节点标记为不可用。 每隔一段固定时间,【服务Consumer】向标记为不可用的节点发起保活探测,若探测成功,就将标记为不可用的节点再恢复为可用态,重新发起调用。
这样【服务Provider】无需再向【注册中心】心跳汇报,【注册中心】中的服务节点信息也不会动态变化,这就是【静态注册中心】。
很多公司也是一开始采用动态注册中心,后来考虑到网络的复杂性,心跳机制不一定可靠,而后开始改为采用服务消费者端的保活机制,事实证明这种机制足以应对网络频繁抖动等复杂场景。
【静态注册中心】中的服务节点信息并不是一直不变,当在
- 业务上线 要把正在部署的服务节点从注册中心中移除,等到服务部署完毕,完全可用的时候,再加入到注册中心
- 运维人工增加或删除服务节点 需要调用注册中心提供的接口,添加节点信息或者删除节点
这些预先感知场景,还是有必要修改【注册中心】中的服务节点信息的。 看起来【静态注册中心】好像退化成了配置中心,只是这时配置中心存储的不是某一项简单的配置,而是某服务的可用节点信息。