Nacos源码解读12——Nacos中长连接的实现
短连接 VS 长连接
什么是短连接
客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
长连接
客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。
长连接的好处
假如请求一个普通的网页 但是这个网页有很多个 css js请求 那每次打开一个网页,基本就要建立几个甚至几十个TCP连接,浪费很多网络资源。如果是长连接的话,那么这么多HTTP请求(包括请求网页的内容、CSS文件、JS文件、图片等)都是使用的一个TCP连接,显然可以节省很多资源。
另外一点,长连接并不是永久连接的。如果一段时间内(具体时间可以在header中进行设置,也就是所谓的超时时间),这个连接没有HTTP请求发出的话,那么这个长连接就会被断掉。
短轮询VS 长轮询
什么是轮询
就比如在飞机上想上厕所 却发现厕所有人需要等待 但是你又不想在那等 就只能回去等 ,但是过一段时间在去 还有人 在接着回去 这么周而复始的去回
短轮询
轮询的原理就是客户端以一定的时间间隔向服务端发出请求,频繁的请求保持客户端和服务端同步。
短轮询最大的问题就是客户端发出请求和服务器端的更新并不是一致的。客户端以固定的频率想服务器发出请求,可能服务器端并没有更新,返回的是个空的信息,等服务器端更新的时候,有可能客户端并没有请求,而且只有最后一次请求才能获得最新数据,这样多次请求不仅浪费了资源,而且并不是实际上的实时更新。
优缺点
优点:后端程序编写比较容易
缺点:请求中有大半是无用,浪费带宽和服务器资源。(而每一次的 HTTP 请求和应答都带有完整的 HTTP 头信息,这就增加了每次传输的数据量)
长轮询
页面发起一个到服务器的请求,然后服务器一直保持连接打开,直到有数据可以发送。
发送完数据之后,浏览器关闭连接,随即又发送一个到服务器的新请求。这一过程在页面打开期间一直持续不断。(在服务端hold住Http请求(死循环或者sleep等等方式),等到目标时间发生,返回Http响应。
长轮询优缺点
优点:在无消息的情况下不会频繁的请求,节省了网络流量,解决了服务端一直疲于接受请求的窘境。
缺点:服务器hold连接会消耗资源,需要同时维护多个线程,服务器所能承载的TCP连接数是有上限的,这种轮询很容易把连接数顶满。
Nacos是怎么处理服务配置修改刷新
1.X版本

客户端启动的时候会初始化一个长连接的线程池定时去 发送pull请求 会发送一个HTTP请求到服务端 在服务端hold住Http请求 超时时间是30秒
30s内 有可能触发变化 push数据到客户端
30s内 数据没有变更超时返回
缺点
30 秒定期创建销毁连接,GC压力大
2.X版本
Nacos 2.x 相比上面 30s ⼀次的长轮训,升级成长链接模式,配置变更,启动建立长链接,配置变
更服务端推送变更配置列表,然后 SDK 拉取配置更新,因此通信效率大幅提升
Nacos长连接源码解析
这里只抓重点 想看详情的话看前面几章
客户端变更推送配置变更事件
/*** adaptor to config module ,when server side config change ,invoke this method.** @param groupKey groupKey*/public void configDataChanged(String groupKey, String dataId, String group, String tenant, boolean isBeta,List<String> betaIps, String tag) {//获取注册的Client列表Set<String> listeners = configChangeListenContext.getListeners(groupKey);if (CollectionUtils.isEmpty(listeners)) {return;}int notifyClientCount = 0;//遍历client列表for (final String client : listeners) {//拿到grpc连接Connection connection = connectionManager.getConnection(client);if (connection == null) {continue;}ConnectionMeta metaInfo = connection.getMetaInfo();//beta ips check.String clientIp = metaInfo.getClientIp();String clientTag = metaInfo.getTag();if (isBeta && betaIps != null && !betaIps.contains(clientIp)) {continue;}//tag checkif (StringUtils.isNotBlank(tag) && !tag.equals(clientTag)) {continue;}//构建请求参数ConfigChangeNotifyRequest notifyRequest = ConfigChangeNotifyRequest.build(dataId, group, tenant);//构建推送任务RpcPushTask rpcPushRetryTask = new RpcPushTask(notifyRequest, 50, client, clientIp, metaInfo.getAppName());//推送任务 向客户端发送变更通知push(rpcPushRetryTask);notifyClientCount++;}Loggers.REMOTE_PUSH.info("push [{}] clients ,groupKey=[{}]", notifyClientCount, groupKey);}
ClientWorker 这里最终会调用 notifyListenConfig方法 这个方法实际上就是往listenExecutebell这个阻塞队列中去offer一个object对象
private void initRpcClientHandler(final RpcClient rpcClientInner) {rpcClientInner.registerServerRequestHandler((request) -> {if (request instanceof ConfigChangeNotifyRequest) {ConfigChangeNotifyRequest configChangeNotifyRequest = (ConfigChangeNotifyRequest) request;LOGGER.info("[{}] [server-push] config changed. dataId={}, group={},tenant={}",rpcClientInner.getName(), configChangeNotifyRequest.getDataId(),configChangeNotifyRequest.getGroup(), configChangeNotifyRequest.getTenant());String groupKey = GroupKey.getKeyTenant(configChangeNotifyRequest.getDataId(), configChangeNotifyRequest.getGroup(),configChangeNotifyRequest.getTenant());CacheData cacheData = cacheMap.get().get(groupKey);if (cacheData != null) {synchronized (cacheData) {cacheData.getLastModifiedTs().set(System.currentTimeMillis());cacheData.setSyncWithServer(false);//向阻塞队列中添加元素 触发长连接的执行notifyListenConfig();}}//返回客户端响应return new ConfigChangeNotifyResponse();}return null;});}
客户端处理变更事件
客户端启动的时候会创建 NaocsConfigService 他的构造方法中会创建一个ClientWorker并启动 然后会执行 startInternal方法 这个方法中会看到 从listenExecutebell中拿数据 listenExecutebell在上文服务配置发生变更的时候会往里面塞一个object 对象 所以这里就能poll队列中出来 如果队列为空等待5秒后执行,如果队列不为空立即执行
@Overridepublic void startInternal() {executor.schedule(() -> {while (!executor.isShutdown() && !executor.isTerminated()) {try {listenExecutebell.poll(5L, TimeUnit.SECONDS);if (executor.isShutdown() || executor.isTerminated()) {continue;}executeConfigListen();} catch (Exception e) {LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);}}}, 0L, TimeUnit.MILLISECONDS);}
executeConfigListen 方法详细看 https://blog.csdn.net/qq_41956309/article/details/134904263这段 下面简述一下
其实就是将3000个配置信息封装成一个CacheData 共用一个TaskId 一个TaskId 对应一个Client连接 然后会发送到服务端 通过比较md5的方式来判断哪些配置发生了变更 然后会返回变更的key 然后客户端遍历返回的有变更信息的key的信息 在去调用服务端查找具体的配置信息 返回客户端然后做返回和动态刷新以及本地缓存的修改

相关文章:
Nacos源码解读12——Nacos中长连接的实现
短连接 VS 长连接 什么是短连接 客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。 长连接 客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立…...
k8s 安装部署
一,准备3台机器,安装docker,kubelet、kubeadm、kubectl firewall-cmd --state 使用下面命令改hostname的值:(改为k8s-master01)另外两台改为相应的名字。 172.188.32.43 hostnamectl set-hostname k8s-master01 172.188.32.4…...
TCP/IP五层(或四层)模型,IP和TCP到底在哪层?
文章目录 前言一、应用层二.传输层三.网络层:四.数据链路层五.物理层:六.OSI七层模型:1.物理层(Physical Layer):2.数据链路层(Data Link Layer):3.网络层(Ne…...
STM32串口接收不定长数据(空闲中断+DMA)
玩转 STM32 单片机,肯定离不开串口。串口使用一个称为串行通信协议的协议来管理数据传输,该协议在数据传输期间控制数据流,包括数据位数、波特率、校验位和停止位等。由于串口简单易用,在各种产品交互中都有广泛应用。 但在使用串…...
LeetCode56. Merge Intervals
文章目录 一、题目二、题解 一、题目 Given an array of intervals where intervals[i] [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input. Example 1: Input: interva…...
【华为OD题库-083】玩牌高手-Java
题目 给定一个长度为n的整型数组,表示一个选手在n轮内可选择的牌面分数。选手基于规则选牌,请计算所有轮结束后其可以获得的最高总分数。 选择规则如下: 1.在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分数,为其新的…...
ARM day3
题目:实现3盏灯的流水 代码: .text .global _start _start: 设置RCC寄存器使能 LDR R0,0X50000A28 LDR R1,[R0] ORR R1,R1,#(0X1<<4) ORR R1,R1,#(0X1<<5) STR R1,[R0]设置PE10管脚为输出模式 LDR R0,0X50006000 LDR R1,[R0] BIC R1,R1,…...
[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-2稳定性分析Stability
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-2稳定性分析Stability 0. 序言1. 稳定的分类2. 稳定的对象3. 稳定的系统4. 系统稳定性的讨论5. 补充内容——Transfer Function(传递函数) - nonzero Initial Condition(非零初始…...
Android Audio实战——音频链路分析(二十五)
在 Android 系统的开发过程当中,音频异常问题通常有如下几类:无声、调节不了声音、爆音、声音卡顿和声音效果异常(忽大忽小,低音缺失等)等。尤其声音效果这部分问题通常从日志上信息量较少,相对难定位根因。想要分析此类问题,便需要对声音传输链路有一定的了解,能够在链…...
PHP基础 - 常量字符串
常量 在PHP中,常量是一个简单值的标识符,定义后默认是全局变量,可以在整个运行的脚本的任何地方使用。常量由英文字母、下划线和数字组成,但数字不能作为首字母出现。 PHP中定义常量的方式是使用define()函数,其语法如下: bool define( string $name, mixed $value [,…...
Linux查看命令的绝对路径
linux查看命令的绝对路径 在Linux中,可以使用以下命令来查看命令的绝对路径: 1、which 命令名 例如,要查看chronyc命令的绝对路径,可以运行: which chronyc 2、whereis 命令名 例如,要查看chronyc命令…...
Docker build 无法解析域名
### 报错 Docker build 无法解析域名 报错:ERROR [ 2/12] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 解决Docker build无法解析域名 # 追加到 etc/docker/daemon.json,注意JSON的格式 {"dn…...
退稿论文重复率太高会怎么样【保姆教程】
大家好,今天来聊聊退稿论文重复率太高会怎么样,希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧: 退稿论文重复率太高会怎么样 在学术出版领域,论文的重复率是衡量其原创性和学术诚…...
Flask 最佳实践(一)
Flask是一个轻量级而强大的Python Web框架,它的简洁性和灵活性使其成为许多开发者的首选。然而,为了确保项目的可维护性和可扩展性,我们需要遵循一些最佳实践。本文将探讨Flask中一些关键的最佳实践。 1. 项目结构 构建一个清晰的项目结构是…...
直流电和交流电
直流电(Direct Current,简称DC)和交流电(Alternating Current,简称AC)是电流的两种基本形式。 1. 直流电 直流电是指电流方向始终保持不变的电流。在直流电中,电子只能沿着一个方向移动。直流电…...
『亚马逊云科技产品测评』活动征文|基于亚马逊EC2云服务器安装Prometheus数据可视化监控
授权声明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 Developer Centre, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器(Elastic Compute Cloud)是亚马…...
15、SQL注入——Sqlmap
文章目录 一、Sqlmap简介1.1 sqlmap可以对URL干嘛?1.2 Sqlmap支持的注入技术1.3 SQLmap检测注入漏洞的流程1.4 Sqlmap的误报检测机制 二、sqlmap基本使用 一、Sqlmap简介 sqlmap使用教程 1.1 sqlmap可以对URL干嘛? 判断可注入的参数判断可以使用哪一种…...
OSPF路由协议
随着Internet技术在全球范围的飞速发展,OSPF已成为目前应用最广泛的路由协议之一。OSPF(Open Shortest Path First)路由协议是由IETF(Internet Engineering Task Force)IGP工作组提出的,是一种基于SPF算法的…...
设计模式-门面模式(Facade)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、定义二、结构 前言 在组件构建过程中,某些接口之间直接依赖会带来很多问题,甚至无法直接实现。采用一层间接接口,来隔离…...
语音识别从入门到精通——1-基本原理解释
文章目录 语音识别算法1. 语音识别简介1.1 **语音识别**1.1.1 自动语音识别1.1.2 应用 1.2 语音识别流程1.2.1 预处理1.2.2 语音检测和断句1.2.3 音频场景分析1.2.4 识别引擎(语音识别的模型)1. 传统语音识别模型2. 端到端的语音识别模型基于Transformer的ASR模型基于CNN的ASR模…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
