心跳机制

目录

TIP

临时实例:实例发起心跳请求,服务端处理请求,并需要进行心跳检测

永久实例:服务端主动发起健康检测

临时实例

客户端

临时实例在注册的时候会开启心跳包,这个在前面有说(默认5s心跳)

1.开启入口

NacosNamingService.registerInstance()

buildBeatInfo就是心跳信息的封装,我们主要看addBeatInfo方法

2.心跳开启

BeatReactor.addBeatInfo()

把心跳任务BeatTask丢到了延迟线程池里面执行,所以主要执行逻辑在BeatTask

3.心跳执行逻辑

BeatTask.run()

1.发送HTTP心跳请求 URL地址为:/nacos/v1/ns/instance/beat

2.如果当前实例在注册中心未找到就重新注册

3.不管结果如何添加心跳任务,继续定时发起心跳(继续将任务丢到线程池里面执行)

心跳请求如下,URL地址为:/nacos/v1/ns/instance/beat

服务端

1.心跳请求的处理

从上面请求URL:/nacos/v1/ns/instance/beat ,我们很容易能找到处理请求逻辑:

InstanceControllerregister.beat()

我这里省略了前面的校验逻辑,直接看主体逻辑:

1.从注册表中获取实例信息,若无则重新注册

2.从注册表中获取服务,若无则直接异常(实例都注册完了,服务还找不到是不合理的)

3.开启异步任务将临时实例状态 置为健康状态,然后返回

2.心跳检测处理

实例如果宕机或者其他什么请求无法发送心跳,那么服务端自然也要对这个实例进行处理,就在服务初始化的时候,会开启会实例的心跳检测任务,上面也有提到过

ServiceManager.putServiceAndInit()

Service.init()

这个内部呢,就会有个ClientBeatCheckTask任务被放入了线程池,5s执行一次

ClientBeatCheckTask.run()

ClientBeatCheckTask任务主要做了两件事:

  1. 找到心跳超时的实例,改变其健康状态,并发布serviceChange事件(后面说),还有实例心跳超时事件
  2. 找到满足删除条件的实例,从注册表中删除该实例信息(HTTP请求调用API,异步删除)
  3. 默认15s超时,30s剔除

永久实例

1.入口

入口和上面临时实例入口差不多,但永久实例是在集群初始化的时候,而临时实例是在服务初始化的时候

Cluster.init如下: 1.检测任务就是HealthCheckTask,这是个异步任务 2.延迟任务第一次(2000ms+5000ms以内随机数)执行,后续在1000ms-5000ms内浮动

HealthCheckTask任务如下:

  1. process方法有多种实现意味着有多种检测方案(这里以TCP为例)
  2. 不管结果如何继续延迟执行,约等于是个定时器(因为每次延迟时间不同)
  3. HealthCheckTask实例化的时候同时初始化了TcpSuperSenseProcessor,该方法是一个Runnable,会执行TcpSuperSenseProcessor.run方法(以TCP为例)

2.获取所有永久实例加入阻塞队列

TcpSuperSenseProcessor .process()

这里会遍历所有永久实例并将实例封装成Beat加入到阻塞队列中

3.从队列中获取实例并封装

上面把永久实例信息放到了阻塞队列中,那么就肯定有方法去取,那是哪里呢?还记得前面说过TcpSuperSenseProcessor本身也是个异步任务吗?

TcpSuperSenseProcessor.run方法如下:

  1. 会先从阻塞队列中取出实例信息并封装,然后尝试与实例建立socket连接
  2. 最后判断连接状态,连接上了就进去实例健康处理并断开连接
  3. 同时会有一个异步的延迟任务,去检测这段时间内是否连接上过,这段时间内没连接上过说明连接超时了
  4. 可以看到这个run方法是个死循环

TcpSuperSenseProcessor.processTask方法如下:

  1. 从阻塞队列中取实例信息,并封装成TaskProcessor异步任务
  2. 批量提交任务,就是执行TaskProcessor异步任务

4.与实例尝试建立连接

TaskProcessor.run()

  1. 主要就是尝试建立socket连接
  2. 开启一个超时检测的延迟任务TimeOutTask(500ms)

5.超时判断

TimeOutTask.run()

因为已经延迟执行了,就判断这段时间内是否连接上过,没有就代表超时,超时会进入finishCheck方法

6.正常处理

前面都执行完了,就到TcpSuperSenseProcessor.run里面最后的PostProcessor异步任务了,连接成功会进入finishCheck方法

PostProcessor.run()

7.最终判断

Beat.finishCheck

连接成功或超时连接都会进到这里处理,不管如何都会发布服务变更事件,只会改变实例状态不会剔除实例

总结

  • 临时实例:
    • 采用客户端心跳检测模式,心跳检测周期5秒
    • 心跳间隔超过15秒(默认)则标记为不健康
    • 心跳间隔超过30秒(默认)则从服务列表删除
  • 永久实例:
    • 采用服务端主动健康检测方式
    • 周期为2000 + 5000毫秒内的随机数
    • 检测异常只会标记为不健康,不会删除
Last Updated: