nacos注册中心源码分析二之服务发现

news2025/1/11 8:56:21

nacos服务发现

服务发现是客户端发起负载均衡(feign)调用接口的时候内部第一次调用nacos服务端接口的时候去调用的
后续调用基本上都是从客户端的缓存列表里边去取,拿不到才会向服务端发起调用

如果想看这一块代码可以看下ribbion源码分析ribbon源码分析

上一篇:nacos服务注册

服务发现源码分析

NamingService为我们提供服务注册和服务发现功能
NacosNamingService是NamingService的实现类
在这里插入图片描述

@Override
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters,
                                      boolean subscribe) throws NacosException {

    ServiceInfo serviceInfo;
    // 判断是否需要订阅服务信息(默认为 true)
    if (subscribe) {
        // 订阅服务信息
        serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
                                                 StringUtils.join(clusters, ","));
    } else {
        // 直接去nacos拉取服务信息
        serviceInfo = hostReactor
            .getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName),
                                              StringUtils.join(clusters, ","));
    }
    // 从服务信息中获取实例列表并返回
    List<Instance> list;
    if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
        return new ArrayList<Instance>();
    }
    return list;
}

HostReactor
com.alibaba.nacos.client.naming.core.HostReactor#getServiceInfo

  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);
        }
        //读取本地服务列表的缓存,缓存是一个Map
        ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);
        //判断川村是否存在
        if (null == serviceObj) {
        	//不存在则构建信息
            serviceObj = new ServiceInfo(serviceName, clusters);
            //加入缓存
            serviceInfoMap.put(serviceObj.getKey(), serviceObj);
            //加入待更新服务列表
            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());
    }

**updateServiceNow(serviceName, clusters);**方法

  private void updateServiceNow(String serviceName, String clusters) {
        try {
            updateService(serviceName, clusters);
        } catch (NacosException e) {
            NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
        }
    }

//调用远程服务
 public void updateService(String serviceName, String clusters) throws NacosException {
        ServiceInfo oldService = getServiceInfo0(serviceName, clusters);
        try {
            
            String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUdpPort(), false);
            
            if (StringUtils.isNotEmpty(result)) {
                processServiceJson(result);
            }
        } finally {
            if (oldService != null) {
                synchronized (oldService) {
                    oldService.notifyAll();
                }
            }
        }
    }



想服务端发起调用
在这里插入图片描述

定时任务同步客户端缓存列表

scheduleUpdateIfAbsent(serviceName, clusters);

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);
        }
    }

在UpdateTask中调用run方法,并切在run方法中调用updateService方法
updateService方法上边已经讲过
在这里插入图片描述

服务端接收客户端请求服务发现接口

/nacos/v1/ns/instance/list
这个就不看了,比较简单

服务端可以参考文档并搜索 拉取服务列表接口:拉取服务列表接口

总结:
Nacos的服务发现分为两种模式:
模式一:主动拉取模式,消费者定期主动从Nacos拉取服务列表并缓存起来,再服务调用时优先读取本地缓存中的服务列表。
模式二:订阅模式,消费者订阅Nacos中的服务列表,并基于UDP协议来接收服务变更通知。当Nacos中的服务列表更新时,会发送UDP广播给所有订阅者。这一种是在服务端界面操作或者主动调用服务注册接口或者下线接口等都会主动推送给客户端需要更改的注册列表
与Eureka相比,Nacos的订阅模式服务状态更新更及时,消费者更容易及时发现服务列表的变化,剔除故障服务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/536275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是互联网交换中心?为什么它很重要?

互联网交换中心&#xff08;Internet Exchange Point, IXP&#xff09;是为促进互联网骨干网的网间互联和公平竞争而设置的运营商间进行数据网际交换的机构&#xff0c;是为互联网业者提供空间进行网络互连、交换流量和资源的服务场所&#xff0c;互联网业者可以在这里利用机架…

基于自定义知识库回答问题的ChatGPT-

前言 ChatGPT是一个强大的语言模型&#xff0c;利用大规模的自然语言处理和机器学习算法&#xff0c;可以进行自然而流畅的对话&#xff0c;理解自然语言问题和回答&#xff0c;相信在座各位&#xff0c;尤其是程序员的你&#xff0c;肯定不可能还没使用过ChatGPT。 ChatGPT能…

属于开发者的交流,openGauss SIG版本规划工作会议来啦!

想参与SIG组未来半年的规划与工作&#xff1f; 想与开发者们近距离探讨需求与解决方案&#xff1f; 想将您的需求合入到openGauss的下个版本&#xff1f; 想在社区年度Summit上展现成果&#xff1f; 那就不能错过这个属于开发者的交流盛会&#xff01; 社区年度开发者大会…

取用水监测计量标准化建设,加强流量在线监测

方案背景 根据《关于强化取水口取水监测计量的意见》、《十四五”节水型社会建设规划》以及《2022年水资源管理工作要点》等政策要求&#xff0c;为强化水资源管理&#xff0c;做好水资源税改革&#xff0c;构建节水型社会&#xff0c;要全面加强取水计量监测设施建设&#xff…

计算机网络实验(ensp)-​实验2:PP协议及PAP认证

目录 实验报告&#xff1a; 实验操作 1.建立网络拓扑图并开启设备 2.修改路由器名字 1.输入命名&#xff1a;sys 从用户视图切换到系统视图 2.输入命名&#xff1a;sysname 姓名 修改路由器名字 3.重复步骤1和2配置每台路由器 3.抓包 1.点击菜单栏的“数…

计算机图形学-GAMES101-6

一、前情提要 在观察和投影变换的基础上提出了视口变换&#xff0c;最终我们会将【-1,1】^ 3 立方体转换到屏幕空间中去。 当所有图像都在屏幕空间中时&#xff0c;我们就要将所有的图像画在屏幕上&#xff0c;这个过程就是光栅化&#xff0c;光栅化就是简单的在屏幕空间的采样…

独家公布!985/211高校毕业生源数量统计Top10揭晓……

2023&#xff0c;985/211高校硕博毕业生总数约达49W。 这是在各大高校官网、官方公众号统计/整理后得到的数据。可能不完全&#xff0c;但数量已经足够庞大&#xff0c;就业竞争也更为激烈。 为了帮助大家更好地了解这些大学的毕业生源情况&#xff0c;本文将为大家揭晓&#x…

Live800:新消费浪潮涌起,在线客服系统如何“升级”?

时代在发展&#xff0c;舞台下的观众已经逐渐成长。 伴随着时代的快速发展&#xff0c;一方面&#xff0c;消费者的行为习惯和消费决策模式变迁&#xff0c;消费者的心理、兴趣及年龄层发生了巨大变化。另一方面&#xff0c;互联网信息透明化打破行业边界&#xff0c;让消费者…

赛效:如何在线变声改变产品宣传片配音

1&#xff1a;打开网页版腾讯智影并登录账号&#xff0c;点击智能小工具里的“智能变声”。 2&#xff1a;我们页面左侧上传音频。 3&#xff1a;试听变声模板后&#xff0c;选择一个模板&#xff0c;点击右下角“制作变声音频并下载”。 4&#xff1a;变声视频声音生成后&…

FastDeploy之hello world(C++)

文章目录 环境准备获取模型和测试图像准备CMakeList.txt准备C推理代码编译可执行程序运行可执行程序可能遇到的问题参考 环境准备 CUDA > 11.2cuDNN > 8.0python > 3.6Linux(x64) 下载FastDeploy C SDK wget https://bj.bcebos.com/fastdeploy/release/cpp/fastdep…

Unity 判断物体是否在阴影中

文章目录 前言效果视频原理步骤源码总结&#x1f4a2;&#x1f4a2;版权声明 前言 如题所示&#xff0c;今天接到的需求是&#xff1a;Unity 判断物体是否在阴影中 效果视频 链接&#xff1a;https://www.bilibili.com/video/BV1wc411N7KF/?vd_source75bbe3d71b926e90fdfca6…

关于argparse和sys.argv的补充

1: sys.argv参考&#xff1a;(10条消息) Python 中 sys.argv 用法详解_ys.journey的博客-CSDN博客 从命令行输入的参数会被保存到sys.argv 2: argparse: 参考&#xff1a;python命令行解析模块argparse用法小结 - 朴素贝叶斯 - 博客园 (cnblogs.com) 除此以外&#xff1a; …

SpringCloud概述

前言 什么是微服务&#xff1f; ​ 微服务是一种面向服务的架构(SOA)风格&#xff0c;其中&#xff0c;应用程序被构建为多个不同的小型服务的集合而不是单个应用程序。与单个程序不同的是&#xff0c;微服务让你可以同时运行多个独立的应用程序&#xff0c;而这些独立的应用…

js文件上传和下载的进度处理

发起请求的方式有Axios、XMLHttpRequest、Fetch Axios Axios下载进度演示-onDownloadProgress <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEe…

【zmq】zguide和cppzmq及windows测试程序

官方的zguide还是有更新的c++例子zguide构建的工程没更新 官方文档说支持3.2   Updated and revised for ZeroMQ/3.2 (older text for ZeroMQ/2.2 still available).libzmq 本身是c++实现的 我现在的libzmq版本是4.3.4,头文件#include <zmq.hpp>

STM32开发(十九)STM32F103 数据手册 —— 低功耗模式解析

文章目录 低功耗介绍stm32 供电框图低功耗模式睡眠模式停止模式待机模式低功耗模式汇总低功耗介绍 系统复位或上电复位后,微控制器进入运行模式。在运行模式下,CPU通过HCLK提供时钟,并执行程序代码。 系统提供多种低功耗模式,可以在CPU不需要运行时进入低功耗模式节省功耗…

一看就会的React入门

目录 简介 入门案例 直接创建 函数式创建 类实例创建 组件实例三大核心属性 state 代码演示 props refs 简介 1). Facebook开源的一个js库 2). 一个用来动态构建用户界面的js库 3). React的特点 Declarative(声明式编码) Component-Based(组件化编码) Le…

生物医学神经网络的方向感

文章目录 A Sense of Direction in Biomedical Neural Networks摘要本文方法Rotation Mechanism 实验结果 A Sense of Direction in Biomedical Neural Networks 摘要 本文描述了一种使模型不仅知道强度&#xff0c;还知道特征方向和尺度等特性的方法。当分析包含诸如血管或纤…

PID单环控制(位置环)

今天我们来聊一聊pid如果控制轮子转动位置 前期准备调试过程 前期准备 需要准备的几个条件&#xff1a; 1.获取实时编码器的计数值 2.写好pid控制算法的函数 3.设定好时间多久执行一次pid计算&#xff0c;并设置限幅输出。 4.多久执行一次pid输出 接下来我们看看这几个部分的…

Vue(ajax、插槽)

一、ajax请求 1. 实现ajax请求方式&#xff1a; xhr&#xff1a;原生 jquery封装xhr axios&#xff1a;属于promise fetch 2. axios实现步骤&#xff1a; 1.首先安装axios //安装 npm i axios 2. 在本地准备两个服务端 //student const express require(express) const a…