当前位置: 首页 > news >正文

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操作&#xff0c;就建立一次连接&#xff0c;任务结束就中断连接。 长连接 客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭&#xff0c;客户端再次访问这个服务器时&#xff0c;会继续使用这一条已经建立…...

k8s 安装部署

一&#xff0c;准备3台机器&#xff0c;安装docker&#xff0c;kubelet、kubeadm、kubectl firewall-cmd --state 使用下面命令改hostname的值&#xff1a;(改为k8s-master01)另外两台改为相应的名字。 172.188.32.43 hostnamectl set-hostname k8s-master01 172.188.32.4…...

TCP/IP五层(或四层)模型,IP和TCP到底在哪层?

文章目录 前言一、应用层二.传输层三.网络层&#xff1a;四.数据链路层五.物理层&#xff1a;六.OSI七层模型&#xff1a;1.物理层&#xff08;Physical Layer&#xff09;&#xff1a;2.数据链路层&#xff08;Data Link Layer&#xff09;&#xff1a;3.网络层&#xff08;Ne…...

STM32串口接收不定长数据(空闲中断+DMA)

玩转 STM32 单片机&#xff0c;肯定离不开串口。串口使用一个称为串行通信协议的协议来管理数据传输&#xff0c;该协议在数据传输期间控制数据流&#xff0c;包括数据位数、波特率、校验位和停止位等。由于串口简单易用&#xff0c;在各种产品交互中都有广泛应用。 但在使用串…...

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的整型数组&#xff0c;表示一个选手在n轮内可选择的牌面分数。选手基于规则选牌&#xff0c;请计算所有轮结束后其可以获得的最高总分数。 选择规则如下: 1.在每轮里选手可以选择获取该轮牌面&#xff0c;则其总分数加上该轮牌面分数&#xff0c;为其新的…...

ARM day3

题目&#xff1a;实现3盏灯的流水 代码&#xff1a; .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

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;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中&#xff0c;可以使用以下命令来查看命令的绝对路径&#xff1a; 1、which 命令名 例如&#xff0c;要查看chronyc命令的绝对路径&#xff0c;可以运行&#xff1a; which chronyc 2、whereis 命令名 例如&#xff0c;要查看chronyc命令…...

Docker build 无法解析域名

### 报错 Docker build 无法解析域名 报错&#xff1a;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&#xff0c;注意JSON的格式 {"dn…...

退稿论文重复率太高会怎么样【保姆教程】

大家好&#xff0c;今天来聊聊退稿论文重复率太高会怎么样&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 退稿论文重复率太高会怎么样 在学术出版领域&#xff0c;论文的重复率是衡量其原创性和学术诚…...

Flask 最佳实践(一)

Flask是一个轻量级而强大的Python Web框架&#xff0c;它的简洁性和灵活性使其成为许多开发者的首选。然而&#xff0c;为了确保项目的可维护性和可扩展性&#xff0c;我们需要遵循一些最佳实践。本文将探讨Flask中一些关键的最佳实践。 1. 项目结构 构建一个清晰的项目结构是…...

直流电和交流电

直流电&#xff08;Direct Current&#xff0c;简称DC&#xff09;和交流电&#xff08;Alternating Current&#xff0c;简称AC&#xff09;是电流的两种基本形式。 1. 直流电 直流电是指电流方向始终保持不变的电流。在直流电中&#xff0c;电子只能沿着一个方向移动。直流电…...

『亚马逊云科技产品测评』活动征文|基于亚马逊EC2云服务器安装Prometheus数据可视化监控

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器&#xff08;Elastic Compute Cloud&#xff09;是亚马…...

15、SQL注入——Sqlmap

文章目录 一、Sqlmap简介1.1 sqlmap可以对URL干嘛&#xff1f;1.2 Sqlmap支持的注入技术1.3 SQLmap检测注入漏洞的流程1.4 Sqlmap的误报检测机制 二、sqlmap基本使用 一、Sqlmap简介 sqlmap使用教程 1.1 sqlmap可以对URL干嘛&#xff1f; 判断可注入的参数判断可以使用哪一种…...

OSPF路由协议

随着Internet技术在全球范围的飞速发展&#xff0c;OSPF已成为目前应用最广泛的路由协议之一。OSPF&#xff08;Open Shortest Path First&#xff09;路由协议是由IETF&#xff08;Internet Engineering Task Force&#xff09;IGP工作组提出的&#xff0c;是一种基于SPF算法的…...

设计模式-门面模式(Facade)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、定义二、结构 前言 在组件构建过程中&#xff0c;某些接口之间直接依赖会带来很多问题&#xff0c;甚至无法直接实现。采用一层间接接口&#xff0c;来隔离…...

语音识别从入门到精通——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模…...

语音识别功能测试:90%问题,可以通过技术解决

现在市面上的智能电子产品千千万&#xff0c;为了达到人们使用更加方便的目的&#xff0c;很多智能产品都开发了语音识别功能&#xff0c;用来语音唤醒进行交互&#xff1b;另外&#xff0c;各大公司也开发出来了各种智能语音机器人&#xff0c;比如小米公司的“小爱”&#xf…...

【Go自学版】01-基础

// 变量 var a, b, c 8, 2.3, "hello" var d float64; e : 6var A []int; var B [10]int; C : [10]int{1, 2, 3, 4} for i : 0; i < len(B); i {} for _, value : range C {} D make([]int, 3) // len 4, cap 10, 扩容方式 cap*2 E : make([]int, 4, 10) E …...

软文开头怎么写才能拿捏用户?媒介盒子为您解答

软文标题是吸引用户点击的关键因素&#xff0c;那软文开头就是决定用户能否读下去的主要因素&#xff0c;很多运营er在写文案时经常会面临的情况之一就是好不容易想到一个标题&#xff0c;点击率不错&#xff0c;但是开头不行用户一看开头&#xff0c;跑了&#xff01;如果不知…...

C语言算法与数据结构,旅游景区地图求最短路径

背景&#xff1a; 本次作业要求完成一个编程项目。请虚构一张旅游景区地图&#xff0c;景区地图包括景点&#xff08;结点&#xff09;和道路&#xff08;边&#xff09;&#xff1a;地图上用字母标注出一些点&#xff0c;表示景点&#xff08;比如&#xff0c;以点 A、B、C、…...

测试:SSE VS WebSocket

SSE&#xff08;Server-Sent Events&#xff09; SSE&#xff08;Server-Sent Events&#xff09;接口是一种实现服务器到客户端单向实时通信的技术。通过SSE&#xff0c;服务器可以主动向客户端推送数据&#xff0c;而不需要客户端不断地向服务器请求数据。这种技术特别适合于…...

Linux+Moba+虚拟机

软件&#xff1a; VMware Workstation ProMobaXterm 简介 是一款由VMware公司开发的强大的虚拟机软件。它可以在单台物理计算机上创建、运行和管理多个虚拟机&#xff0c;每个虚拟机都可以独立运行不同的操作系统和应用程序。 功能&#xff1a; 虚拟化&#xff1a;能…...

快手数仓面试题附答案

题目 1 讲一下你门公司的大数据项目架构&#xff1f;2 你在工作中都负责哪一部分3 spark提交一个程序的整体执行流程4 spark常用算子列几个&#xff0c;6到8个吧5 transformation跟action算子的区别6 map和flatmap算子的区别7 自定义udf&#xff0c;udtf&#xff0c;udaf讲一下…...

如何在Go中编写包

包由位于同一目录中的Go文件组成,这些文件在开头具有相同的package语句。你可以从包中包含额外的功能,使程序更复杂。有些包可以通过Go标准库获得,因此与Go安装一起安装。其他可以使用Go的go get命令安装。您还可以通过使用必要的package语句在要共享代码的相同目录中创建Go…...

JVM类加载全过程

Java虚拟机类加载的全过程&#xff0c;即加载&#xff0c;验证&#xff0c;准备&#xff0c;解析&#xff0c;初始化 一、加载 加载 是 类加载过程中的一个阶段&#xff0c; 有以下三部分组成 1&#xff09;通过一个类的全限定名来获取定义此类的二进制流 2&#xff09;将这…...

Uniapp安卓原生插件开发Demo

文章目录 前言一、安装开发工具二、导入uni插件原生项目三、开发Module四、开发Component五、合并原生代码到uniapp项目中总结 前言 当HBuilderX中提供的能力无法满足App功能需求&#xff0c;需要通过使用Andorid/iOS原生开发实现时&#xff0c;可使用App离线SDK开发原生插件来…...