翻牌源码之Nacos--配置中心实现 二

本文围绕Nacos配置中心,详细解析了客户端请求服务端检查配置变化的流程。从ClientWorker的checkUpdateConfigStr方法,到服务器的ConfigServletInner的doPollingConfig方法,深入探讨了长轮询机制。包括如何实现长时间等待和及时响应配置变化,以及相关事件触发和响应逻辑。

书接上回配置中心实现一

直接找到client请求server询问有无配置发生改变的地方,也就是com.alibaba.nacos.client.config.impl.ClientWorker#checkUpdateConfigStr方法。

根据红框圈住的部分的path:/v1/cs/configs/listener,在服务器中找到对应的处理请求地址的部分:

MD5Util.getClientMd5Map方法获取客户端想要知道的,服务端配置是否有变化的那部分key的请求,然后通过处理得到一个map。带着这个请求,来到了com.alibaba.nacos.config.server.controller.ConfigServletInner#doPollingConfig方法。

主要处理部分在红框部分,从上述客户端请求代码可以看见,客户端是渴望进行长轮询的,所以这里的if条件为真。直接进入到com.alibaba.nacos.config.server.service.LongPollingService#addLongPollingClient方法一探究竟就可以了。

这里的大部分逻辑都在红框中标注了,要特别说明的是req.startAsync()方法,会获得一个javax.servlet.AsyncContext对象,用来进行异步的调度servlet。简单来说就是,在调用了startAsync()方法取得AsyncContext对象之后,此次请求的响应会被延后,并释放容器分配的线程

有修改很简单,直接返回哪个修改了给客户端就行,那当前没有修改的呢,这里又是如何让客户端实现长时间的等待,而有了修改又能及时响应的效果的呢?这一切的秘密目前看来,都在上图中的最后一段代码中。重中之重就是这个类com.alibaba.nacos.config.server.service.LongPollingService.ClientLongPolling。一起跟着构造方法进去看看。

构造方法很简单,就是给自己的成员变量赋值。重要的是将从request中得到的javax.servlet.AsyncContext对象和clientMd5Map给保存了下来。看完构造方法,我们进一步的去看看这个类,发现是一个Runnable接口的实现,二话不说,run方法肯定是所有功能的入口,直捣黄龙即可。

原来,服务器部分实现等待长时间返回的法宝是执行一个计划执行的线程方法。长轮询则等待timeoutTime的时长,直接返回配置没有改变的结果。那么如果是固定的在timeoutTime时间后,直接返回配置没有改变的结果,那又是如何做到配置一有改变,客户端就立马能收到响应的呢?这时,我看见有这么一段代码:allSubs.add(this)。而在延迟执行的run方法中,对应的有allSubs.remove(ClientLongPolling.this),这是在干啥呢?

为了一探究竟,先要看看allSubs是啥。

是一个对列,那哪里用了这个队列呢?这个确实不好找了,但是我想到,这个队列里存放的是com.alibaba.nacos.config.server.service.LongPollingService.ClientLongPolling对象,如果要执行什么方法的话,肯定也是这个对象了里的方法。我们先把这个对象的方法看一下:

除了构造方法和run方法这里只剩下两个方法了。一个是sendResponse,一个是generateResponse方法,根据观察,发现generateResponse只有sendResponse调用了,那么,如果allSubs取出ClientLongPolling有什么动作的话,肯定就是sendResponse方法了。我们具体来看一下这个方法:

通过上边的代码可以看出,配置信息如果发生了变化,这里会终止掉延迟线程,直接组织响应信息返回。是这个地方没错了。那又是什么机制让配置文件的变化能够直接体现在这里呢?我们跟着sendResponse方法网上跟,来到关键所在。

又是一个Runnable接口的实现,如下所示:取出allSubs队列中内容,如果改变了的配置信息包含在监听的map中,那么就把当前ClientLongPolling在队列里剔除掉,然后执行上边提到的sendResponse方法。

那么又引出一个问题,com.alibaba.nacos.config.server.service.LongPollingService.DataChangeTask这个Runnable是从哪里调用的呢?往上跟一下:

猜想:肯定是配置文件修改之后,经过一系列的操作之后,触发了com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent事件,然后订阅了这个事件的com.alibaba.nacos.config.server.service.LongPollingService#LongPollingService会根据allSubs中监听的配置key进行对比,匹配则返回配置已被修改的结果,最中通过response进行响应,达到一有修改就立马返回到client端的效果。至于LocalDataChangeEvent事件如何发出,现在先不考虑,毕竟发布订阅模式做的就是解耦,那个是另一个功能的事情了。

顺带一提,代码里一直有个isFixedPolling()的判断,我判断是兼容另一个不是长轮询的模式用的,通过分析可以看出,那种模式不会在配置修改后立马返会结果。

好了,Nacos配置中心获取配置与监听配置到这里就结束了。当然,里边还有好多知识,比如如果服务器是集群,为什么我只请求了一个服务,而当其他服务器发生变化之后我还是能立马感知到呢?这个问题,后续在来解决吧。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值