0 前言
注册中心不应仅提供服务注册和发现功能,还应保证对服务可用性监测,对不健康的服务和过期的进行标识或剔除,维护实例的生命周期,以保证客户端尽可能的查询到可用的服务列表。
因此本文介绍Nacos注册中心的健康检查机制。
1 注册中心的健康检查机制
知道⼀个服务是否还健康的方式:
- 客户端主动上报,告诉服务端自己健康状态,如果在⼀段时间没有上报,那么我们就认为服务已经不健康
- 服务端主动向客户端进行探测,检查客户端是否还被能探测到
如你在废墟中大声呼叫救援队并且提供你的位置和健康信息,相比搜救队用探测设备挨着废墟探测会使探测队的工作量减轻很多,他可专注尽快将你救出。好比注册中心对服务健康状态的检测,如所有服务都要注册中心主动探测,由于服务的数量远大于注册中心的数量,那么注册中心的任务量将会比较巨大。那就都采用服务主动上报健康检查。那如果在废墟之下的我们因为身体状况无法呼救,那么搜救队就会放弃搜救了吗?当然不是,搜救队肯定也会对废墟进行全面探测将你救出。如服务本身就没法主动进行健康上报,那么这个时候注册中心主动检查健康状态就有用武之地。
在当前主流的注册中心,对健康检查机制主要都采用TTL(Time To Live),即客户端在⼀定时间没向注册中心发心跳,注册中心认为此服务不健康,进而触发后续剔除逻辑。
对主动探测,根据不同场景,要采用的方式有不同。
Nacos 健康检查机制
既然以上两种健康检查机制都有应用的场景,且适用场景不⼀致,Nacos 对健康检查的机制如何抉择?
2 Nacos服务的特点
Nacos 提供两种服务类型供用户注册实例时选择:
- 临时实例,临时存在于注册中心,在服务下线或不可用时被注册中心剔除。临时实例会与注册中心保持心跳,注册中心在⼀段时间没收到来自客户端的心跳后就将实例设置为不健康,然后在⼀段时间后剔除
- 永久实例在被删除之前会永久的存在于注册中心,且可能不知道注册中心存在,不会主动向注册中心上报心跳,这时就要注册中心主动探活
可见Nacos两种健康探测方式均有被使用,Nacos监看检查的整体交互如下:
来看Nacos对两种实例的健康检查机制。
3 临时实例健康检查机制
可通过两种方式进行临时实例注册,通过:
- Nacos 的 OpenAPI
- 或 Nacos 提供的 SDK
进行服务注册,OpenAPI注册方式实际是用户根据自身需求调 Http 接口对服务进行注册,然后通过 HTTP 接口发送心跳到注册中心。在注册服务同时会注册⼀个全局的客户端心跳检测的任务。在服务⼀段时间没有收到来自客户端的心跳后,该任务会将其标记为不健康,如果在间隔的时间内还未收到心跳,那么该任务会将其剔除。
SDK注册方式实际是通过 RPC 与注册中心保持连接(Nacos 2.x中,旧版还是仍通过OpenAPI),客户端会定时通过 RPC 连接向 Nacos 注册中心发心跳,保持连接的存活。如客户端和注册中心的连接断开,注册中心会主动剔除该 client 所注册的服务,达到下线效果。
Nacos 注册中心还会在注册中心启动时,注册⼀个过期客户端清除的定时任务,删除那些健康状态超过⼀段时间的客户端。
对不同类型使用方式,Nacos 对健康检查的特点都相同,都是由客户端向注册中心发送心跳,注册中心会在连接断开或是心跳过期后将不健康的实例移除。
4 永久实例健康检查机制
Nacos 中使用 SDK 对于永久实例的注册实际也是使用 OpenAPI 的方式进行注册,这样可以保证即使客户端下线后也不会影响永久实例的健康检查。
永久实例的的监看检查,Nacos采用注册中心探测机制,注册中心会在永久服务初始化时,根据客户端选择的协议类型注册探活的定时任务。Nacos 现在内置提供了三种探测的协议,即Http、TCP 及 MySQL 。
MySQL 主要用于特殊业务场景,如数据库的主备需通过服务名对外提供访问,需要确定当前访问数据库是否为主库时,那么我们此时的健康检查接口,是⼀个检查数据库是否为主库的 MySQL命令。
因为持久化服务的实例的在被主动删除前⼀直存在,探活的定时任务会不断探测服务健康状态,并将无法探测成功的实例标为不健康。
但有时:有些服务不希望校验其健康状态,Nacos 也提供白名单配置,用户可将服务配置到该白名单,Nacos放弃对其健康检查,实例健康状态始终为用户传入的健康状态。
5 集群模式下的健康检查机制
完整的注册中心应具备高可用,即注册中心可集群部署作为⼀个整体对外服务。不同于单机部署,集群部署中我们的客户端只和其中⼀个注册中心服务保持链接和请求,但我们的服务信息需要注册到所有的服务节点上,在其他客户端从任意⼀个注册中心服务获取服务列表时始终是所有的服务列表。此时Nacos在集群模式下又如何对不是和自己保持心跳连接的服务进行健康检查?
对集群下的服务,Nacos⼀个服务只会被 Nacos 集群中的⼀个注册中心负责,其余节点的服务信息只是集群副本,用于订阅者在查询服务列表时,始终可获取到全部服务列表。临时实例只对其被负责的注册中心节点发送心跳信息,注册中心服务节点会对其负责的永久实例进行健康探测,在获取到健康状态后由当前负责的注册中心节点将健康信息同步到集群中的其他的注册中心。
服务的注册从注册方式维度可分:
- 通过 SDK RPC 连接进行注册,客户端会和注册中心保持链接
- 通过 OpenAPI 进行 IP 和端口注册
第⼀类如何找到对其负责的注册中心节点?只需和注册中心集群的任⼀台节点建立联系,由这节点负责这客户端。注册中心会在启动时注册⼀个全局的同步任务,将其当前负责的所有节点信息同步到集群中其他节点,其他非负责的节点也会创建该客户端的信息,在非负责的节点上,连接类型的客户端,会有续约时间,在收到其他节点的同步信息时,更新续约时间为当前时间,如在集群中的其他节点⼀段时间内没收到不是自己的负责的节点的同步信息,那认为此节点已不健康,从而达到对不是自己负责的节点健康状态检查。
第二类方式也基本和第⼀类⼀致,OpenAPI 注册的临时实例也是通过同步自身负责的节点到其他节点来更新其他节点的对应的临时实例的心跳时间,保证其他节点不会删除或者修改此实例的健康状态。前面我们特别指明了是临时实例而没有说所有实例,你应该也可能会想到这种方式对于持久化节点会显得多余,永久实例会在被主动删除前⼀直存在于注册中心,那么我们健康检查并不会去删除实例,所以我们只需要在负责的节点永久实例健康状态变更的时候通知到其余的节点即可。
6 总结
本文从注册中心场景展开,详细介绍 Nacos 注册中心的健康检查机制。
Nacos针对不同类型的服务,使用不同健康检查方式进行实例生命周期维护,⼀致性协议使 Nacos 节点均保持实例生命周期的⼀致。
Nacos 注册中心集群中,实例的健康状态和生命周期需要保持⼀致,因此后文介绍 Nacos 注册中心是如何使用 Nacos 的⼀致性协议,来保持数据模型及生命周期⼀致。
本文由博客一文多发平台 OpenWrite 发布!