Spring Cloud 2.2.2 源码之四十九nacos客户端触发服务刷新原理三

服务获取和刷新的流程图

在这里插入图片描述

NacosNamingService的selectInstances

前面说了,负载均衡器初始化的时候会最后调用NacosNamingServiceselectInstances方法,最终到这里,因为是订阅标记是true,所以直接走hostReactor.getServiceInfo,内部如果发现服务有更新会进行监听器的通知,所以叫做订阅:
在这里插入图片描述

HostReactor的getServiceInfo

先判断容灾模式,如果已经出故障了,直接从本地缓存读取。否则就尝试获取服务信息,如果没有就创建一个,然后立即去注册中心获取服务,这里用了一个updatingMap来表示再更新的服务,然后进行更新,里面涉及更新后的结果和老的做比对,如果有改变,会对Notifier任务进行改变通知,其实就是改变了阻塞队列changedServicesNotifier检查到他有改变,就会进行处理,去通知监听器有NamingEvent事件,不过貌似目前还没有监听这个事件的监听器。完了最后再判断是否这个服务已开启UpdateTask任务更新,没有的话就开启一个UpdateTask任务进行更新,这里才是真正更新服务,对已有的服务进行更新,而负载均衡的PollingServerListUpdater任务,更多的是获取服务,真正的服务更新还是UpdateTask任务做的。

    public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {

        NAMING_LOGGER.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
        String key = ServiceInfo.getKey(serviceName, clusters);
        if (failoverReactor.isFailoverSwitch()) {//已经到容灾模式
            return failoverReactor.getService(key);
        }

        ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);

        if (null == serviceObj) {//不存在就创建
            serviceObj = new ServiceInfo(serviceName, clusters);

            serviceInfoMap.put(serviceObj.getKey(), serviceObj);
            //updatingMap表示在更新了
            updatingMap.put(serviceName, new Object());
            updateServiceNow(serviceName, clusters);
            updatingMap.remove(serviceName);

        } else if (updatingMap.containsKey(serviceName)) {
            //正在更新实例
            if (UPDATE_HOLD_INTERVAL > 0) {
                // hold a moment waiting for update finish
                synchronized (serviceObj) {
                    try {
                        serviceObj.wait(UPDATE_HOLD_INTERVAL);
                    } catch (InterruptedException e) {
                        NAMING_LOGGER.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
                    }
                }
            }
        }

        scheduleUpdateIfAbsent(serviceName, clusters);

        return serviceInfoMap.get(serviceObj.getKey());
    }

HostReactor的scheduleUpdateIfAbsent

双重检测,添加一个UpdateTask任务。这个任务具体干什么,我在前面的文章
里有,就不多说了。

 public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
        if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
            return;
        }

        synchronized (futureMap) {
            if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
                return;
            }

            ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
            futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
        }
    }

如果有新的服务获取到,或者有服务改变了,Notifier任务会感知到,然后去通知监听器,不过没监听器监听NamingEvent事件:
在这里插入图片描述

PushReceiver接受推送

一旦注册中心有服务改变了,就会进行推送,如果发现是dom类型的,表示有更新,所以就调用hostReactor.processServiceJSON,内部会进行更新,通知等操作,具体跟前面讲过的updateServiceNow的结果处理一样:
在这里插入图片描述

然后根据类型进行相应的应答UDP报文就好了:
在这里插入图片描述
因为你请求刷新的时候会把UDP端口传过去:
在这里插入图片描述

好了,服务刷新是如何做到的,是什么时候刷新的现在基本已经了解了吧,除了自己去更新服务信息,服务端还会UDP推送过来。 流程图也有了,可以自己debug一下加深理解,当然还有细节只能自己看啦,面面俱到我也做不到。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值