服务的健康检查

几乎所有提供服务注册与发现的组件都支持对服务进行健康状态的检测,以便于及时发现和解决服务问题。常见的健康检查策略分两种方式,一种是客户端主动上报自身健康状态,另一种则是服务端主动探测客户端的健康状态。在nacos中,临时服务对应主动上报健康信息,持久服务则对应服务端下探服务健康状态。

| 客户端上报

| 服务端下探

| 自我保护

| 一些注意事项

一、客户端上报

1、上报设定

在nacos中,所有注册的服务默认均为临时服务,也就是说这些服务默认均开启了主动上报自己健康信息的功能,默认上报间隔时间为5秒,如果15秒未上报,服务被标记为不健康服务,30秒未上报会剔除该服务,可通过heart-beat-interval来自定义这个时间,实际使用时为了快速检查和响应服务健康状态,一般会做如下上报参数的设定,如:

spring:
  cloud:
    nacos:

      discovery:
        ### 实例上报心跳间隔时间(毫秒)
        heart-beat-interval: 1000
       
### 实例上报心跳超时时间(毫秒)
        heart-beat-timeout: 3000
       
### 实例超时心跳被剔除时间(毫秒)
        ip-delete-timeout: 3000

说明:

服务实例注册后,会将上面的心跳设定规则同步到给该服务,作为后续该服务主动上报的规则使用。

2、如何发送beat

在nacos的client模块中,通过NamingProxy.sendBeat(…)来定时发送心跳beat上报,它会以http方式调取naming模块的/v1/ns/instance/beat接口发送心跳。

然后,通过HealthCheckReactor.scheduleNow(…)以多线程方式异步发送BeatTask任务,也就是Runnable检查任务。

二、服务端下探

默认情况下,nacos使用了tcp方式检查服务的健康状态,并且默认使用IP端口检查,而默认的端口为80,默认20秒探测一次,若探测失败则判别服务为不健康服务,但服务不会从nacos中移除。这些信息从nacos ui后台可清楚看到,当然,nacos还提供了http方式检查,需要我们手动配置,具体如下:

1、下探规则

1.1 TCP检查

TCP检查的基本逻辑就是对与服务关联的channel不断的ping服务的IP+端口port,进而记录和判别服务健康情况。

1.2 HTTP检查

HTTP检查的基本逻辑也比较简单,就是通过HttpAsyncClient不断对服务的IP+端口port+自定义服务接口地址进行访问,如果返回200,则代表服务是健康的。当然,如果不设定“自定义服务接口地址”,则直接检测IP+Port,具体如下:

2、集群下健康检查

集群环境下的服务健康检查,就是每个服务对应其分配的某个注册中心实例,对于临时实例:当注册中心接收到来自客户端主动上报的健康信息后,其会同步该信息到其它注册中心节点;而永久实例:当负责的注册中心所下探服务的健康信息发生改变后,其会同步变动信息到其它注册中心,进而实现集群下服务的健康检查功能。

3、为什么支持两种健康检查

当流量洪峰到来时,势必要比平时流量高出很多,那么就需要更多的服务实例来均衡应对高并发情况,当这波大流量过后,就不需要这么多服务实例了,所以临时实例比较适合此场景。当然,对于一些常备的服务实例,则需要持久化实例比较合适。

三、自我保护机制

Nacos为每个服务提供了保护阀值,其值范围在0-1之间,当服务实例健康个数占比(健康实例个数/总实例个数)小于这个保护阀值时,为降低服务雪崩的可能,也会向不健康实例发送请求,虽然牺牲了部分请求,但也起到了均摊流量的作用,避免整体系统无法提供服务的风险,这是值得的,这个阀值可在nacos ui后台手动设定,如下:

说明:

什么是服务雪崩?如服务调取顺序:A->B->C ,当A服务调用B服务,B服务调用C服务时,正常情况下,如果C服务有5个实例,每个实例能够达到的QPS为200,那么整个C服务可以达到1000的QPS,如果C服务宕掉了3个服务实例,注册中心通知B服务目前只有2个实例可用,那么每个C实例每秒均需要接收500次请求,显然大大超出了实例的性能范围,可能会停止服务,接着B服务也会停止服务,接着A服务也无法提供服务,这引起了服务级联崩掉的现象被称为“服务雪崩”。

四、一些注意事项

1、客户端上报

建议修改默认相关心跳上报时间,以适应实际环境下快速响应服务健康状态的处理,一般建议做如下设定,详细上面有介绍:

### 实例上报心跳间隔时间(毫秒)
heart-beat-interval: 1000
### 实例上报心跳超时时间(毫秒)
heart-beat-timeout: 3000
### 实例超时心跳被剔除时间(毫秒)
ip-delete-timeout: 3000

注意:

一般情况下,都会设置一个网关Gateway来统一管理进出,如果Gateway使用了如ribbon等负载策略时,单单修改客户端的上报时间是不够的,还需要修改ribbon的相关时间,如下:

ribbon:
  ServerListRefreshInterval:
3000

这样整体的最大时间可能为客户端上报的3秒,再加上ribbon的间隔时间3秒,所以最多可能时长为6秒才能上下线服务。

2、服务端下探

一般情况下,我们大多选择默认的TCP下探方式来检查服务健康情况,如果当服务下线后,我们有某些自定义行为的,一般可选择HTTP方式来下探服务健康情况。

3、保护阀值

服务的保护阀值主要就是为了预防流量洪峰时,因为原服务的某些实例不能正常工作,进而请求会堆压在正常服务的少许实例上,可能会导致服务宕掉,进而引起服务雪崩问题,增加这个阀值后,即使服务实例宕掉了,nacos依然分配流量给它,虽牺牲了一些流量,但保住了服务整体正常提供服务,一般常见设置这个阀值在0.75~0.85之间,具体请根据流量峰值设定。

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐