《springcloud 之 nacos源码下》

一、服务发现(客户端)

因为服务发现很简单,就直接上图了,大家可以根据图就可以很好理解,其实和注册的思想一样最终还是会调到reqApi 发送查询服务列表的url调用服务端

 

 

 

 这里讲一下

ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);   这里首先第一次查询服务肯定是为空
if (null == serviceObj) {  如何为空,就把空的服务对象放进 客户端本地服务的缓存列表中
serviceObj = new ServiceInfo(serviceName, clusters);

serviceInfoMap.put(serviceObj.getKey(), serviceObj); 客户端本地服务的缓存列表中map
    updatingMap.put(serviceName, new Object());
updateServiceNow(serviceName, clusters); 然后更新服务列表
updatingMap.remove(serviceName);

 

 大家看到这里应该就明白了,和注册一样通过代理类调用查询方法

 在看这里UtilAndComs.nacosUrlBase + "/instance/list"  这个url 肯定对应了服务端的url

 

 

第一次拿为空,所以执行上面的一些列方法,后面客户端就会定期的去注册表里查询服务,然后读回到自己本地缓存,代码如下

 通过线程读取注册表,然后put到客户端本地缓存中

服务发现(客户端)总结: 客户端都是通过nacosNamingService开始的, 首先客户端会先去自己的本地缓存map 获取服务列表,通过ribbon负载均衡去服务提供方获取服务,但是第一次进来时候客户端本地缓存为空,所以回去调用updataServiceNow方法里面的rqi()方法调用服务端的获取列表的url,去获取服务,拉去服务回来后,放到客户端本地的缓存中,下次客户端就会先通过自身本地缓存获取服务,  通过客户端走了定时方法, 定时回去服务端拉去服务

 

·二、服务发现(服务端)这里就不多介绍了,自己看绝对一目了然,直接上图

通过客户端发送请求url 查询服务列表,请求到服务端

 

  上面的这个方法获取Service ,放下滚动还是在这个方法中调用了下面这个方法

 

 点击下面clusterObj.allIPs()这个方法就可以获取·所有的实例

 

 服务发现(服务端)其实服务端就是最后调用了allIPs()方法去临时的set集合里获取服务,因为当时我们注册的时候就是注册在了cluster里面的临时set集合里

三、发送心跳(客户端)

首先注册的时候,调用BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);这个方法

  点击方法进入,创建了BeatInfo,类 并把Period心跳时间设置为5秒

 

 

 设置完5秒中后,调用beatReactor.addBeatInfo(groupedServiceName, beatInfo);

 调用线程池,每隔5秒中向服务端发送心跳

 实现Runnable 执行run方法

 

 看下图 ,就知道了 ,有一次拼接url 调用reqApi方法,发送服务端心跳服务,对应的是nacos官网

 

发送心跳(客户端)总结: 服务注册的时候,会判断如果是临时实例,就是调用发送心跳的方法,每5分钟调用一次,发送给服务端

四、接受心跳(服务端)

首先咱们上面说了,客户端回没5秒中给服务端发送心跳,所以服务端接受请求后,就回去看自己注册表里的服务是否在健康,如果注册表里的服务实例当时记录的时间过长,意思就是当前的系统时间减去服务实例注册的时候的时间大于了15秒,他们服务端就认为这个服务已经挂掉,然后就回置为flase,最终删除掉,大体就是看代码看图

 

 上面其实就是获取到客户端传来服务  IP,端口,心跳等等,然后调用handleBeat()方法进行心跳健康检查

 

下面这个clientBeatProcessor是一个线程,肯定会执行run方法

 

 

大家看到这个run方法里面画红框的地方就是彻底明白了吧, 其实服务端就是接受到客户端发送心跳后,就会把当前这个服务的最后时间更新为系统当前时间,用来后期判断服务实例的健康情况

 

当前上面上说的更新时间, 其实在更新时间的前, 会走下面的方法逻辑,去先判断服务列表中的实例是否在健康范围内,如果超过15秒,健康状态改为false,如果超过30秒直接服务下线

 就是把客户端发来的心跳和服务名称进行注册,在注册的逻辑中又会调用心跳检查方法

 

 这个参数是一个线程,所以会执行run方法clientBeatCheckTask

 下面这个里就是当前系统时间减去实例上次最后记录的时间,如果大于15秒,就会把实例置为false

  下面这个里就是当前系统时间减去实例上次最后记录的时间,如果大于30秒,就会删除实例

 

 

nacos 集群下的心跳设计思想,大家看下面这个方法就可以了, 我就不点进去看了,这个方法其实就是获取到集群下服务名称做了一个取模运算,只获取到一台机器然后进行心跳健康检查任务,其他的服务就retrun掉了,如果其中有一台机器挂掉后, 取模就会去剩下的有几台机器的数量

 

 

集群下的多态机器下的状态是如何同步?

ServerListManager 这个类在项目启动的时候加载这个类

 

 执行完构造方法后, 会执行init方法

 

 这两个对象就是线程,具体看里面的逻辑就可以了

 

然后进去里面后,发现里面获取所有的服务, 执行了send方法,然后调用http请求发送集群下所有节点的状态(同步状态)

 

 

 

 

 

 

 

 集群下的新增的数据是如何同步?

在注册服务的时候,会调用同步方法

 

 进行遍历,遍历的意思就是除了自己获取到所有的节点,然后进行同步

 

 

到这里,咱们nacos源码差不多就算讲完了,基本就是围绕这 服务注册 ,服务发现,服务健康状态检查, 心跳机制, 服务下线来讲的!

 

 

这里再补充一下nacos的作为配置中心

spring读取所有PropertySourceLocator的方式是基于SPI机制的;

springcloud提供了PropertySourceLocator接口支持扩展自定义配置加载到spring Environment中。

NacosPropertySourceLocator 实现了PropertySourceLocator接口

 

看上面的这个红框, 就明白了 现在加载了共享,后加载了扩展,然后加载了application, 这样就明白了吧 后加载的文件肯定是覆盖了前面,所以后加载的文件优先使用

 

CAP原则   AP架构   CP架构

 

posted @ 2021-11-15 21:00  毅静  阅读(144)  评论(0)    收藏  举报