关于rpc长连接与短连接的思考记录

文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实际应用中需要根据具体情况选择长连接还是短连接,并讨论了负载均衡器在RPC中的作用

目录
  • rpc项目中的长连接与短连接的思考
    • 什么是rpc项目中的长连接和短连接
    • 与tcp和http的长连接短连接的异同
    • 客户端与服务器有哪几种连接模式与利弊分析
      • rpc连接的三种方式:
    • 长连接不是银弹
      • 1. client 和 server 的数量
      • 2. 负载均衡机制
    • 关于tcp一些其他层面的优化
      • 总结

      对于rpc项目,在接受大佬指导的时候曾问过对于长连接和短连接是如何处理的,在面试的时候也被问起socket​是长连接还是短连接,发现自己没有好好思考过这个问题,因此好好总结一下。

      前置知识点:rpc基础,tcp基础

      rpc项目中的长连接与短连接的思考

      什么是rpc项目中的长连接和短连接

      和http的长连接和短连接的概念类似,rpc项目中的短连接是指处理完一次rpc请求后就断开连接,长连接是指处理完一次rpc请求后不断开连接,复用连接。

      甚至很多rpc的底层实现就是http协议,因此长连接和短连接很类似就不足为奇了。

      http中长连接是指处理完一次http请求和响应之后不断开tcp连接;http短连接是指处理完一次http请求和响应之后断开tcp连接(需要注意的是:一般是服务器断开,至于为什么是服务器断开,则又是一篇小文章了hhh)。

      与tcp和http的长连接短连接的异同

      ​rpc​和http​的长短连接的异同上文已经分析过了,本质上没什么区别,都是控制​tcp​的断开时机。
      而tcp长连接平时聊的很少,很多人甚至不清楚tcp也是有“长连接”机制的,其名字叫做 tcp的保活机制(keep-aliving),其会在长时间没有信息交流的时候向对端发送探测报文,并且在一定次数没有回复后就断开连接。

      tcp的保活机制与现在常见的探测机制非常相似(服务探活、rpc探活等),但是大家基本都没有采用tcp的保活机制,而是采用自己的保活机制,原因在于tcp保活机制的探测时间太长了,在默认设置下,2个多小时才能探测出对端已经挂掉,具体见:浅谈 tcp 保活机制

      这里也涉及一个平时很容易弄错的地方了,比如tcp的保活机制(keep-aliving​)与http协议的长连接(Connection: Keep-Alive​)英文很相似,但是本质上不是一个东西。

      客户端与服务器有哪几种连接模式与利弊分析

      rpc连接的三种方式:

      常规 RPC 的连接模型主要有三种:

      短连接:每次请求都创建新连接,得到返回后立即关闭连接 长连接池:单个连接可以处理多个请求和返回,但同时只能处理一次完整请求与返回 连接多路复用:单个连接可以同时异步处理多个请求与返回

      每类连接模型没有绝对好坏,取决于实际使用场景,一般来说连接多路复用性能最好。

      这些应该是一些比较成熟的rpc框架实现的,中间配有负载均衡器才能实现连接池的操作。

      如果是客户端与服务端直连,本质上就是两种:长连接和短连接。

      长连接不是银弹

      本节主要说明长连接虽然相对于短连接一般情况下性能好,但是不是十全十美,必须有所考量。

      1. client 和 server 的数量

      ​rpc​长连接模式下相比于rpc​短连接,在相同client​数量的情况下,需要维系的连接数更多(连接一般不会断开,或者是需要超时或者是其他情况才会断开),因此当client​数量相比于server数量过多的时候,使用长连接会有以下几个问题:

      ​server​需要维护数量众多的连接,压力很大。 端口很容易耗尽

      因此在client​数量特别多的情况下就不适合用长连接了,用短连接反而合适一些。

      使用长连接的时候也需要考虑超时断开等机制。

      所幸rpc​服务器一般来说client​的数量相比于网页服务器等会少很多,因此使用长连接应该就可以了。

      2. 负载均衡机制

      现代后端服务端架构中, 为了实现高可用和可伸缩, 一般都会引入单独的模块来提供负载均衡的功能, 称为负载均衡器。根据工作所在的OSI​层级的不同, 不同的负载均衡器会提供不同的转发功能。

      不同的均衡器是根据工作在OSI​的层级进行区分的,以最常见的 L4负载均衡器(工作在 TCP​层)和 L7负载均衡器(工作在应用层, 如HTTP​)两种负载均衡器来举例分析这两种负载均衡器对与rpc的影响。

      当然,不一定需要一个单独的一个组件来完成负载均衡,实际上,很多项目中都是采用直接在客户端进行负载均衡的操作(胖客户端)来避免引入单独的负载均衡器。

      L4 负载均衡器

      L4工作在TCP层,就是对TCP的流量进行负载均衡的转发,由于TCP的特性,因此L4的负载均衡器并不能知道某次rpc请求是否处理完毕,只是在发起请求的时候进行负载均衡处理(选择要转发到哪个服务器上)。

      ​​

      这样对RPC的影响是什么

      如果rpc是长连接:长连接情况下client​会一直保持和某个server​的连接,这样的话在client与server建立连接之后负载均衡就失效了。但是新的​client​连接进来的时候还是会负载均衡的。这样容易导致在client​数量很少的时候会导致流量分发不平均:​ 如果rpc是短连接:每次请求都会重新连接,因此每次都会负载均衡。

      L7 负载均衡器

      L4负载均衡在长连接情况下导致负载均衡在某种意义下失效的本质原因是负载均衡器在第一次连接的时候负载均衡后,后续不会再负载均衡了。

      相比 L4 只能基于连接进行负载均衡, L7 由于在HTTP层进行负载均衡,其可以进行 HTTP​ 协议的解析。当 client 发送请求时, client​会先和 L7 握手, L7 再和后端的一个或几个 server​ 握手,并根据不同的策略将请求分发给这些server​,从而实现基于请求的负载均衡。

      ​​

      L7均衡器无论是长连接还是短连接都不会有L4在长连接情况下的负载均衡的问题,原因是因为L7可以进行HTTP协议的解析,从而可以在client无感知的情况下进行切流。

      这也是大家最广泛使用的负载均衡的手法!

      因此使用长连接还是短连接必须要根据实际情况来确定,不能无脑的选择长连接。

      关于tcp一些其他层面的优化

      即对socket​ tcp​编程的优化,我们可以考虑如下两个方向:

      ​TCP_NODELAY​:禁用 Nagle​ 算法,使小数据包能够及时发送。 ​TCP_QUICKACK​:启用 quickack​ 模式,减少应答延迟。

      总结

      从本文可知,rpc的负载均衡实现主要有3种:胖客户端、L4层负载均衡、L7层的负载均衡,在现实中,L4层的负载均衡器一般用于中央交换机这样的装置,因此后端开发的同学一般是不会接触到的。

      而抛开L4负载均衡来说,现实中L7和胖客户端的负载均衡一般来说也是混合使用的,不会单独使用。

      比如说一个经典的集群维度的负载均衡示例图如下:

      一般来说至少有2层的负载均衡,分别保证集群维度的高可用和集群内部服务的高可用。

      集群维度的负载均衡用于保证集群维度的高可用:一般采用胖客户端的方式,选择一个固定的集群进行连接使用,除非当前集群出现问题,否则一般不会切换。 集群内部服务的负载均衡用于保证服务内部的高可用:一般会使用L7的负载均衡器(如NGINX)进行转发。通常情况下客户端与负载均衡器的长短连接由于客户端决定,而负载均衡器与服务器之间采用长连接以避免tcp握手,提高响应速度。

      无论是哪种维度的高可用保证,本质上都是为了防止“单点”问题。

      到此这篇关于关于rpc长连接与短连接的思考记录的文章就介绍到这了,更多相关rpc长连接与短连接内容请搜索骃骐网以前的文章或继续浏览下面的相关文章希望大家以后多多支持骃骐网!

      您可能感兴趣的文章:

      • 通过 Redis 实现 RPC 远程方法调用(支持多种编程语言)
      • Python中实现远程调用(RPC、RMI)简单例子
      • Java利用Sping框架编写RPC远程过程调用服务的教程
      • RPC、RMI、SOAP的区别详解
      • php实现的一个简单json rpc框架实例
      • python使用rpc框架gRPC的方法
      • 对python调用RPC接口的实例详解
      • Java实现简单的RPC框架的示例代码

      相关推荐:

      如何解决Python测试中数据库连接频繁开闭问题_利用fixture的yield模式

      pytest fixture 中用 yield 管理 pymysql 连接更稳,因其确保无论测试是否异常都会执行清理;应避免全局连接池、多次 close、共享连接,并在 yield 前 ping 保活和重置状态。 频繁在 pytest 测试中用 pymysql.connect() 打开又关闭数据库连接,不是“看起来不优雅”的问题,而是会直接拖慢测试执行、触发 MySQL 的 max_connect...

      如何解决Python连接远程Linux服务器慢的问题_通过Paramiko优化

      根本原因是SSH握手阶段的DNS反向解析;远程sshd配置UseDNS yes时,会对客户端IP执行阻塞式gethostbyaddr()查询,无PTR记录或DNS慢则卡住30秒,Paramiko connect()随之挂起。 根本原因不是代码,而是SSH握手阶段的DNS反向解析。Python用paramiko连接远程Linux服务器时卡在connect()、耗时十几秒甚至超时,大概率不是网络延迟,...

      Python 使用 Pika 库连接 RabbitMQ 总是频繁因 “Heartbeat Timeout” 断开连接怎么办?

      根本原因是心跳协商失败或中间设备干扰;需禁用heartbeat=0、设heartbeat=30、同步配置connection_attempts≥3和retry_delay=2,并确保HAProxy超时≥60s且禁用httpchk。 根本原因不是网络不稳定,而是客户端与服务端心跳协商失败或被中间设备干扰——多数情况只需调整两个参数就能稳定住连接。 为什么 heartbeat 参数设成 0 反而更易断...

      Python 3 中使用 Pika 检查 RabbitMQ 连接的正确方法

      在 Python 3 中,pika.BaseConnection 是抽象基类,不可直接实例化;应改用其具体子类(如 BlockingConnection)来建立连接并进行健康检查。 在 python 3 中,`pika.baseconnection` 是抽象基类,不可直接实例化;应改用其具体子类(如 `blockingconnection`)来建立连接并进行健康检查。 Pika 库自较新版本起(尤...

      Python 3 中使用 Pika 检查 RabbitMQ 连接的正确方式

      Python 3 的 Pika 库中 BaseConnection 是抽象基类,不可直接实例化;应改用其具体子类(如 BlockingConnection)来建立连接并进行健康检查。 python 3 的 pika 库中 `baseconnection` 是抽象基类,不可直接实例化;应改用其具体子类(如 `blockingconnection`)来建立连接并进行健康检查。 在将旧版 Python ...

      FastAPI框架中怎么优雅地管理RabbitMQ的生命周期(启动连接与关闭)?

      必须用 lifespan 而非 on_event 初始化 RabbitMQ 连接,因 lifespan 是原生异步上下文管理器,确保连接池和通道池就绪后才接收请求;on_event 为同步钩子包装的协程,不等待初始化完成即放行请求,易致首几个请求抛出 ConnectionRefusedError 或 ChannelClosed。 直接用 lifespan 管理 rabbitmq 连接,别再碰 @a...

      Python开发Flask应用如何记录日志_配置logging模块实现分级输出

      Flask默认不记录日志到文件,需手动配置logging:添加FileHandler(推荐RotatingFileHandler)和StreamHandler,统一设level为INFO,并禁用gunicorn冲突输出;模块日志应按功能命名如'app.models'以精准定位。 Flask默认不记录日志到文件,必须手动配置logging模块 Flask开发时,app.logger默认只输出到std...

      JavaEE怎么连接CSS_JavaEE项目引入CSS样式文件方法教程

      JavaEE项目中CSS文件应放在webapp/css等公共目录,并通过${pageContext.request.contextPath}或动态引用,避免路径错误导致样式失效。 JavaEE项目要引入CSS样式文件,核心其实就两点:文件放对位置,然后在页面里正确引用。这事儿说起来简单,但实际操作中,尤其是在部署到不同环境时,路径问题常常让人头疼。 解决方案 在JavaEE项目里引入CSS样式文件...

      如何在PHP环境中集成MongoDB?PHP与MongoDB的连接配置教程

      首先安装MongoDB PHP扩展并启用,然后通过Composer安装mongodb/mongodb库,接着使用Client类连接数据库并执行增删改查及聚合操作,最后通过配置连接池参数优化性能。 要在PHP环境中集成MongoDB,你需要安装MongoDB的PHP扩展,配置连接参数,然后就可以通过PHP代码操作MongoDB数据库了。 解决方案 安装MongoDB PHP扩展: 通过PECL安装(...