返回顶部

Nacos入门

1. Nacos入门

1.1. 前言

我的初衷是想搞一套适合自定义快速开发的框架,把一些必要的技术整合进来,第一想法是尝试下SpringCloud Alibaba,毕竟是阿里开发,适应国人需求,下载源码本打算研究下,看了nacos,就想到之前项目用的Eureka,而我也深知Eureka真的只是单纯的注册中心,需要配置属性还要依赖git做配置中心,所以改用nacos或许也是不错的主意,于是开始研究nacos

1.2. 部署配置

我这入门和普通的运行demo入门不一样,直接看源码说话,先把SpringCloud Alibaba的git代码下下来

由于nacos是个单独部署的服务,所以先去Nacos官网安装好nacos,账号密码都是nacos,修改配置文件nacos地址

UTOOLS1587006812859.png

1.3. 控制台配置

  1. 可以看到上述配置文件,明显一个dataId对应了一个配置文件,group做为分组参数,我们可以再nacos界面进行配置
    UTOOLS1587007099274.png

UTOOLS1587007136853.png

点击发布,确认后就可以更新到应用,那么现在来研究它的原理

1.4. 调试分析

1.4.1. 获取配置

随意发布更新一个配置看到打印参数

UTOOLS1587007279721.png

那么进ClientWorker类,可以看到一个单独的线程池负责了数据的接收

UTOOLS1587008234346.png

其中核心的更新配置方法为checkUpdateDataIds,而该方法内部的核心方法为checkUpdateConfigStr,其核心内容如下

UTOOLS1587008427496.png

明显可以看到一个远程post调用的方法,此方法用来获取nacos的最新配置,到这里可能要问了,明明是nacos修改配置推送给客户端,为什么是客户端调用服务端?这里nacos用了个巧妙的方法,设置较长的超时时间,看截图可以看出,超时时间为45秒,实际上nacos在30秒的时候若没有修改数据,就会返回空数据表示没有更新,若30秒以内有更新数据,则可以在这个45秒的请求中直接返回,看到这个设计我还真有点佩服作者脑洞的,这样做相当于把心跳和数据传输结合起来了,不需要再额外搞个心跳连接,一旦nacos挂了,客户端就会报错,客户端在请求则nacos也知道客户端存活。我能想到的劣势,或许就是这样的长连接不能搞太多吧,但一般服务连接也够了

接下来进入方法parseUpdateDataIdResponse,该方法用来确认修改了哪份配置,真正修改系统配置的还要回去继续看

UTOOLS1587113169850.png

可以看到changedGroupKeys为改变的文件,nacos在拿到改变文件名称后,会通过getServerConfig方法主动去获取改变数据

UTOOLS1587113440349.png

之后通过LocalConfigInfoProcessor.saveSnapshot在本地存一个快照,更新本地缓存cacheMap

1.4.2. 刷新配置

  1. 遍历缓存配置文件名
    UTOOLS1587176202353.png

  2. 检测数据变化

UTOOLS1587176288333.png

  1. 刷新属性值

UTOOLS1587178947860.png

  1. 刷新容器,加载新的配置文件

UTOOLS1587180002722.png

  1. 加载对应环境配置文件
    UTOOLS1587188713982.png

  2. 资源定位器
    UTOOLS1587180364218.png

  3. 读取位置,这里读取的是故障转移文件,也就是可以放自己的配置文件在nacos故障的时候可以使用

UTOOLS1587181016398.png

  1. 一般没有故障转移文件,则远程调用获取正确配置

UTOOLS1587188316038.png

  1. 构建PropertySource

UTOOLS1587188516105.png

1.5. 总结

整个流程下来可以总结为几步

  1. 保持远程连接,拉取改变的文件名
  2. 根据拉取的文件名,dataId等参数获取真正的配置数据
  3. 更新缓存中配置,这里我发现好多地方都会经过configFilterChainManager.doFilter(null, cr),我通过反射添加了过滤器,结果一次文件更新会调用好多遍doFilter,目前没搞清它的意义是什么
  4. 发布配置更新事件RefreshEvent,会重新加载propertySource,过程中会远程调用Nacos再次去调用最新配置

1.6. 问题

没想明白这冗余的设计,随着源码的深入,真的反转反转再反转,剧情跌宕起伏

  1. 我以为在阻塞请求中会直接返回改变的配置参数,结果返回的是nacos中配置的文件名,好吧,这也可以理解,文件名用来定位具体的propertySource也行,但为什么不和改变参数一起返回;
  2. 那好,根据第一次返回的参数再去远程调用获取配置,我以为可能只返回修改的参数,返回的却是整个文件参数,好吧,这样容错更好也能理解,就是一次可能传递的数据量会比较多,似乎和apollo的设计不同
  3. 我以为拿到数据应该会去更新环境变量,刷新实例了,但是也没有,对着缓存操作了一通,然后直接刷新Spring容器,通过它早就定义好的资源定位器,重新远程读取配置内容,刷新到propertySource
  4. 好吧,中间的一系列操作,我姑且认为为其它依赖做准备,但多次出现的configFilterChainManager.doFilter(null, cr)又看不懂了,看名字应该是链式过滤器,但哪有过滤器再一次更新中调用3次以上的,而且在没刷新容器之前,也起不到过滤作用吧;
  5. 并且这个过滤器定义了add方法,但我没找到入口可以添加,只能通过反射强制读出属性进行过滤器的添加
  6. 我也看到了listener.receiveConfigInfo(contentTmp);这么个方法,这个更像是对用户提供的配置内容读取方法,若想要拿到配置变动后新的配置信息,可别用filter去了,实现的例子如下

UTOOLS1587198454703.png

posted @ 2020-04-18 16:32  老梁讲Java  阅读(3213)  评论(0编辑  收藏  举报