阅读 46

nacos配置中心

背景

如果只是简单的系统和应用也用不上配置中,当系统架构负载起来,为了方便的管理各个应用的配置,我们可以通过配置中心如nacos、apollo等,来实现一些配置变更、版本管理、灰度上线等功能;

作为配置中心,配置的实时变更应该是一个基础功能,那nacos是怎么实现他的呢

推还是拉

有这两种实现方式来实现实时变更:

由服务端发起,配置变更后一一推送给有注册过客户端,通过长链接可以保证推送的实时性,但是长链接可能会进入假死状态,即看着是连接着的,实际人早没了。所以还需要心跳机制来保证联通。

拉(pull)模型,其实说白了就是客户端轮询,轮询也分长轮询和短轮询;

短轮询就是每隔一段时间查询一次。时间间隔设置太长,实时性会变差;设置过短,会影响客户端性能; 相对比长轮询就是一种更好的解决方案,长短说的不是轮询的间隔时间,而是轮询一次的时间;

长轮询,每次查询服务端,服务端如果有变更记录就直接返回,如果没有就hang住一段时间,如果在hang住的这段时间内,变更事件发生了,就会返回给客户端。这样在实时性和轮询次数上做了个平衡。

nacos的实时配置变更下发就是通过长轮询的方式做到的;

服务端代码解析

configController

客户端通过 /v1/cs/configs/listener 接口来发起一次长轮询。这个接口完成了两个工作,

  1. 查询客户端传进来的配置文件md5和服务端的配置文件md5是否一致,如果不一致则直接返回结果;
  2. 如果一致,则陷入长轮询状态,等待配置变更时间发生,直到超时时间;

image.png

那么我们关心的长轮询逻辑就能找到了在doPollingConfig方法中了。


image.png 这里判断header里是否有 Long-Pulling-Timeout ,如果没有则不是长轮询。


那么我们继续往 longPollingService.addLongPollingClient 里面走。

image.png

圈起来的第一部分是配置是否变更的double-check和超时时间的处理,这里就不赘述了;

直接看第二部分,通过获取 asyncConetext 将这次请求转为异步请求,然后讲这些参数一起塞到了ClientLongPolling 里面去了,看名字应该是长轮询的处理逻辑了。

获取asyncContextservlet3.0的一个功能,通过asyncContext我们将耗时的任务放到工作线程中去,执行结束后在异步响应,这样我们就可以释放当前的servlet worker线程,提升我们服务端的吞吐量了。

AsyncContext asyncContext = request.startAsync();
//结束请求 返回响应
asyncContext.complete();
复制代码

image.png

ClientLongPolling的功能就是等待到超时。超时之后自动返回;

长轮询的任务进来后,都会被塞到 allSubs 队列中,等待启动的这个定时任务delay时间已过,就先移除任务,然后再校验一遍配置变更,然后异步响应;

是不是很奇怪这个长轮询的流程都走没了,都没有看到哪里有配置实时推送的逻辑, 别着急仔细想想,我们怎样才能知道配置变更过了呢?

当然是在控制台变更或客户调用publish方法的时候,埋点记录一下,再通知给还在allSubs队列中客户啦;


那我们来找下这段逻辑吧

ConfigController.publishConfig

image.png

在配置发布接口中被我发现了, 看来是配置的变更被包装成了一个配置变更事件通知给用户

ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime()));
复制代码

然后我在 LongPollingService 的构造方法中看到了她注册了一个配置变更事件,当publish发生时,在ConfigChangePublisher 中注册过的事件就会执行了。

image.png

我们终于找到事件变更的主角了 DataChangeTask


image.png

这里面也就两步,

  1. 轮询allSubs队列中的客户端,
  2. 将和这次变更事件有影响的客户端,结束长轮询,响应出去

长轮询就此结束


总结

  1. 利用asyncContext释放servlet线程,保证吞吐量,提高效率;
  2. 通过ClientLongPolling等待,通过DataChangeTask取消等待,返回结果;
  3. 通过观察者模式事件通知,来实时捕获到配置的变更;

参考

Nacos配置中心交互模型是 push 还是 pull

文章分类
后端
文章标签