服务器的心跳协议,Nacos服务端心跳续约

先看下服务端处理的InstanceController概览图:

4da87304db75

InstanceController概览图

当客户端调用reqApi向服务器发送Http PUT心跳请求,URI是/nacos/v1/ns/instance/beat,对应的controller就是InstanceController的beat方法。beat方法首先检查Instance是否存在,Instance不存在的情况:比如客户端超过30秒没有向服务器发送心跳,这时服务端会删除这个实例,30秒后再发送心跳时就会出现Instance不存在的情况。

说回来,如果实例不存在,并且客户端也没有发送BeatInfo包,这时会返回给客户端一个实例不存在的错误;如果Instance实例不存在,但客户端发送了BeatInfo包,这时能拿到BeatInfo里的信息,beat方法就会创建Instance对象,并调用ServiceManager类的registerInstance方法注册服务实例。

这个BeatInfo包就是客户端发送心跳时判断的参数:Light_Beat_Enabled,如果这个参数是false就发送,默认值就是false,这个逻辑在讲客户端时讲过一遍了。

我们具体看下InstanceController类beat方法代码:

4da87304db75

InstanceController类beat方法-1

4da87304db75

InstanceController类beat方法-2

4da87304db75

InstanceController类beat方法-3

ServiceManager类getInstance方法涉及到Service、Cluster、Instance的内存数据结构,服务注册就是把数据写到这几个类的关键变量中,服务发现也是从这几个类的变量中查找,所以这几个类的数据结构非常重要。

首先,Service服务是存储在ServiceManager类的serviceMap变量里,类型是:

Map> serviceMap = new ConcurrentHashMap<>();

Map里key含义如下:Map(namespace, Map(group::serviceName, Service))

serviceMap是个双层Map结构,先用namespace拿到该名字空间的所有Service,再用serviceName拿到Service对象。

Cluster集群存在Service类的clusterMap变量里,类型是:Map clusterMap = new HashMap<>();Map里key含义:Map;clusterMap中存储该service所有的集群,使用clustername可以直接拿到Cluster对象实例。

Instance分为临时服务和永久服务,是分开存的,在Cluster类中的2个变量里:

Set persistentInstances = new HashSet<>()   //永久服务实例

Set ephemeralInstances = new HashSet<>()  //临时服务实例

persistentInstances中是该集群中所有永久服务的Instance的集合;ephemeralInstances 是该集合中所有临时服务的Instance的集合,Instance对象是对应Ip、port、healthy等属性。

ServiceManager类getInstance就是从上面几个变量结构中查找到具体的Instance实例,如果数据结构中没有就创建一个Instance对象,然后调用ServiceManager类的registerInstance方法注册实例,registerInstance注册实例就是向那几个数据结构Map中塞数据,然后把注册数据再同步到nacos服务器集群其他节点。这个registerInstance注册服务逻辑后面会介绍。

接着看InstanceController类beat方法最后一段代码:

4da87304db75

InstanceController类beat方法-4

首先组装心跳基本属性到clientBeat对象,传给Service的processClientBeat方法,processClientBeat拿到ip和port就可以找到Instance,然后做该Instance的心跳续期。下面是给客户端设置心跳间隔时间和是否发送心跳BeatInfo对象,这2个属性设置后会覆盖默认属性(心跳间隔默认是5秒,默认发送BeatInfo),设置后返回给客户端后,客户端就按这个最新的属性设置发送心跳。之前在客户端上报心跳逻辑时,也详细讲过这2个属性。上面代码可以看出设置这2个属性的值是从nacos控制台拿到的,用户在控制台上可以设置这2个属性的metadata元数据,这个之后可以看下怎么在控制台设置这些元数据。

好了,InstanceController类beat方法我们说完了。

我们接着看下Service类的处理心跳方法processClientBeat,这个是服务端心跳的核心逻辑,见下图,只剩下最后这一个了:

4da87304db75

InstanceController类beat流程

看下processClientBeat代码:

4da87304db75

processClientBeat方法

这段代码很简单,创建一个处理心跳的处理器任务ClientBeatProcessor,然后扔到线程池中立即执行,见scheduleNow方法。我们看下ClientBeatProcessor这个线程怎么处理心跳的?

先看第一段,取出该服务的必要属性,主要是取出该服务的所有Instance,后面做遍历找要上报心跳的Instance。

4da87304db75

ClientBeatProcessor线程-1

再看最后一段:

4da87304db75

ClientBeatProcessor线程-2

这段是心跳服务续约的核心逻辑,先在所有Instance里找到匹配上报心跳的Instance,然后设置该实例的最后上报时间,nacos就是根据这个属性判断15秒心跳超时、30秒删除实例。然后刷新下实例的健康属性,比如上次心跳15超时,这个health属性会被设置成false,这次上报后会重置成健康true。最后调用PushService组件,该组件是通过udp协议向客户端推送服务变更信息,这个后面有详细说明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值