RPC异步化原理

news2024/11/18 9:45:07

深入RPC,更好使用RPC,须从RPC框架整体性能考虑问题。得知道如何提升RPC框架的性能、稳定性、安全性、吞吐量及如何在分布式下快速定位问题。RPC框架如何压榨单机吞吐量?

1 前言

TPS一直上不去,压测时CPU压到40%~50%就再也压不上去,TPS也不提高,咋办?

看业务逻辑,在执行较为耗时的业务逻辑基础上,又同步调用了好几个其它服务。由于这几个服务的耗时较长,导致服务业务逻辑耗时也长,CPU大部分时间都在等待,没得到充分利用,因此CPU利用率和服务吞吐量上不去。

3 RPC调用吞吐量的影响因素

根本原因:由于处理RPC请求较耗时,且CPU大部分时间都在等待而没有去计算,导致CPU利用率不够。好比一个人干活,但他没规划好时间,且长时间都闲着,当然也就完不成太多工作。

导致RPC请求耗时的原因主要在RPC框架本身吗?除非在网络较慢或使用方使用不当,否则大多情况,刨除业务逻辑处理的耗时时间,RPC本身处理请求的效率就算在较差环境也不过ms级。可以说RPC请求耗时大部分是业务耗时,如业务逻辑中有访问DB执行慢SQL的操作。所以,大多情况,影响RPC调用吞吐量原因就是业务逻辑处理慢,CPU大部分时间都在等待资源。

找到根因,对症下药,

3 提升单机吞吐量的方案

响应式开发就是为提升业务处理的吞吐量。提升吞吐量的关键:“异步”。我们的RPC框架要做到完全异步化,实现全异步RPC。试想一下,如果我们每次发送一个异步请求,发送请求过后请求即刻就结束了,之后业务逻辑全部异步执行,结果异步通知,这样可以增加多么可观的吞吐量?

效果不用我说我想你也清楚了。那RPC框架都有哪些异步策略呢?

4 调用端如何异步?

最常用方式就是返回Future对象的Future或入参为Callback对象。Future是最简单的一种异步方式。

发起一次异步请求,并从请求上下文拿到一个Future,之后就可调用Future#get获取结果。

业务逻辑中调用好几个其它服务,若同步调用,假设调用4个服务,每个服务耗时10ms,则业务逻辑执行完至少耗时40ms。采用Future,连发4次异步请求并拿到4个Future,由于异步调用,耗时几乎忽略不计,之后统一调用这几个Future#get。业务逻辑执行完的时间理想情况10ms,耗时整整缩短到原四分之一,即吞吐量可能提升4倍。

5 RPC框架Future异步实现

一次RPC调用本质:调用端向服务端发一条请求消息,服务端收到消息后进行处理,处理后响应给调用端一条响应消息,调用端收到响应消息后再处理,最后将返回值给到动态代理。

对调用端,向服务端发送请求消息与接收服务端响应消息,是两个完全独立过程,大多数情况下都不在一个线程进行。是不是说RPC框架的调用端,对RPC调用的处理逻辑,内部实现就是异步的?是的。

对RPC框架,无论同步 or 异步调用,调用端内部实现都是异步。

调用端发的每条消息都有个唯一标识,调用端向服务端发请求消息前,会先创建一个Future,并存储消息标识与这Future的映射,动态代理所获得返回值最终就是从这Future中获取。当收到服务端响应消息,调用端会根据响应消息的唯一标识,通过映射找到对应Future,将结果注给那个Future,再处理,最后动态代理从Future得到返回值。

  • 同步调用,不过是RPC框架在调用端处理逻辑中主动执行Future#get,让动态代理等待返回值
  • 异步调用,则是RPC框架没有主动执行Future#get,用户可以从请求上下文得到这Future,自己决定何时执行Future#get

Future示意图

现在你应该很清楚RPC框架是如何实现Future方式的异步了。

6 RPC调用全异步

Future异步是调用端异步的一种方案,那服务端是否需异步,有何实现方案?

RPC服务端接收到请求的二进制消息后,据协议拆包解包,之后将完整消息解码并反序列化,得到入参后,再通过反射执行业务逻辑。生产环境中这些操作都在哪个线程执行?

当然不在一个线程,对二进制消息数据包拆解包的处理是一定在处理网络I/O的线程,若网络通信框架使用Netty,则对二进制包处理在IO线程,而解码与反序列化过程一般也在IO线程处理。

服务端业务逻辑应交给专门业务线程池处理,以防止由于业务逻辑处理过慢而影响网络I/O处理。

我们配置的业务线程池的线程数都有限,业务线程池的线程数一般只会配置到200,因为大多情况下线程数配置到200还不够用,说明业务逻辑该优化。但若碰到特殊业务场景,让配置的业务线程池打满了。

案例

启动一个服务,业务逻辑处理得就是较慢,当访问量逐渐变大,业务线程池很容易打满,吞吐量不理想,这时CPU利用率也很低。咋办?

调大业务线程池的线程数?有更好方案吗?服务端业务处理逻辑异步是个好方案。

调大业务线程池的线程数

勉强可解决这问题,但对RPC框架,往往都有多个服务共用一个线程池情况,即使调大业务线程池,较耗时服务很可能还会影响其它服务。最佳方案:能让业务线程池尽快释放,就需RPC框架支持服务端业务逻辑异步处理。

7 服务端业务逻辑异步方案

较难处理,因为服务端执行完业务逻辑后,要对返回值序列化并编码,将消息响应给调用端,但若是异步处理,业务逻辑触发异步后方法就执行完了,来不及将真正结果进行序列化并编码后响应给调用端。

就要RPC框架提供一种回调方式,让业务逻辑可异步处理,处理完后调用RPC框架回调接口,将最终结果通过回调响应给调用端。

可让RPC框架支持CompletableFuture,实现RPC调用在调用端与服务端之间完全异步,发布一个RPC服务,服务接口定义返回值CompletableFuture对象。

调用过程

  • 服务caller发起RPC调用,直接拿到返回值CompletableFuture对象,之后无需任何额外与RPC框架相关操作(如Future方式时需通过请求上下文获取Future的操作),直接就可异步处理
  • 在服务端业务逻辑,创建一个返回值CompletableFuture对象,之后服务端真正业务逻辑可在一个线程池中异步处理,业务逻辑完成之后,再调用这CompletableFuture对象的complete方法,完成异步通知
  • 调用端在收到服务端发过来的响应后,RPC框架再自动调用调用端拿到的那个返回值CompletableFuture对象的complete方法
  • 一次异步调用完成

通过CompletableFuture,RPC框架可真正做到在调用端与服务端间完全异步,同时提升调用端与服务端的两端的单机吞吐量,并且CompletableFuture是Java8原生支持,业务逻辑中没有任何代码入侵性。

8 总结

影响RPC调用的吞吐量主要原因:服务端的业务逻辑比较耗时,并且CPU大部分时间都在等待而没有去计算,导致CPU利用率不够,而提升单机吞吐量的最好办法就是使用异步RPC。

RPC框架的异步策略主要是调用端异步与服务端异步。调用端的异步就是通过Future方式实现异步,调用端发起一次异步请求并且从请求上下文中拿到一个Future,之后通过Future的get方法获取结果,如果业务逻辑中同时调用多个其它的服务,则可以通过Future的方式减少业务逻辑的耗时,提升吞吐量。服务端异步则需要一种回调方式,让业务逻辑可以异步处理,之后调用RPC框架提供的回调接口,将最终结果异步通知给调用端。

另外,我们可以通过对CompletableFuture的支持,实现RPC调用在调用端与服务端之间的完全异步,同时提升两端的单机吞吐量。

其实,RPC框架也可以有其它的异步策略,比如集成RxJava,再比如gRPC的StreamObserver入参对象,但CompletableFuture是Java8原生提供的,无代码入侵性,并且在使用上更加方便。如果是Java开发,让RPC框架支持CompletableFuture可以说是最佳的异步解决方案。

9 FAQ

提升RPC调用吞吐量,还有啥解决方案?

RPC调用方式

sync

默认方式,但这只是『方法』内部同步,在RPC框架内部还是异步处理。

future 方式

消费者得到 future,自行决定何时获取返回结果。

callback 方式

调用端无需同步处理响应结果,可直接返回。最后返回结果在回调线程里异步处理。

oneway 方式

调用端发送请求之后,无需接受响应

Dubbo 2.7后使用 CompletableFuture 提升异步处理能力,支持以上四种方式。

CPU大部分时间都在等待,并未得到充分利用,因此CPU利用率和服务吞吐量当然上不去了。对于这段话,其实线程处于等待状态时,不占用CPU资源。更准确的描述:浪费宝贵线程资源,大量线程处等待状态,可能(不是一定)导致CPU利用率低。

使用异步的时候返回的速度变快了,但是后台所需要的线程数会变少吗?,线程池我理解还是被打满?

异步对于服务提供方来说,RPC线程所要处理的事情就变少了。

压榨单机吞吐量的秘诀是异步化,针对RPC框架异步化分成:

  • 调用端,本就是异步化,毕竟通过网络发生完请求消息,后面就是黑盒,此时可选择不让RPC调用端框架拿服务端的响应消息,让调用端应用自行选择何时拿。这样调用端就能发送更多的请求消息,提高吞吐量
  • 服务端异步化,核心在于重分利用单机服务端的资源,避免CPU闲置,业务处理线程处于等待状态

若“业务线程池的线程数配置到200”,线程池被打满了,若单纯增加线程数量有用吗?200个线程都处理不了的话,配置到300或500不是只会增加CPU上下文切换时间吗?

可能用处不大,需提高接口性能或者扩容解决。

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

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

相关文章

Windows离线安装rust

目前rust安装常用的方式就是通过Rustup安装,此安装方式需要访问互联网。在生产环境中由于网络限制,不能直接访问互联网或者不能访问目标网站,这时候需要用离线安装的方式,本文将详细介绍离线安装步骤,并给出了vscode如…

记一次java.lang.ClassNotFoundException问题排查过程

记一次java.lang.ClassNotFoundException问题排查过程 同事提供一个or-simulation-engine.jar包(非maven项目,内部依赖很多其他jar,这个包是手动打出来的)给我,我集成到我的springboot项目中,在本地IDEA启…

网上招聘系统

技术:Java、JSP等摘要:当今,人类社会已经进入信息全球化和全球信息化、网络化的高速发展阶段。丰富的网络信息已经成为人们工作、生活、学习中不可缺少的一部分。人们正在逐步适应和习惯于网上贸易、网上购物、网上支付、网上服务和网上娱乐等…

C#多窗口切换

多窗口切换【功能目标】1、实现多窗口切换(Panel)2、动态生成窗口内文本框以及标签(重点)3、改变文本框内容【效果图】【代码详解】1、多窗口切换如要实现多窗口切换,需要用到Panel,对于这个控件不熟悉的可…

正演(1): 二维声波正演模拟程序(中心差分)Python实现

目录 1、原理: 1)二维声波波动方程: ​编辑 2)收敛条件(不是很明白) 3)雷克子波 4)二维空间衰减函数 5)边界吸收条件 (不是很明白。。) 2、编程实现 1)参数设置&…

RNN相关知识总结

目录RNN结构与原理1.模型总览2.反向传播LSTM结构与原理1.模型总览2.如何解决RNN梯度消失/爆炸问题?GRU结构及原理1.模型总览LSTM与GRU的区别RNN结构与原理 1.模型总览 上图是RNN的展开结构图,由输入层、隐藏层和输出层组成。当前时间步t 的隐藏状态hth_…

Spark 分析计算连续三周登录的用户数

前言:本文用到了窗口函数 range between,可以参考这篇博客进行了解——窗口函数rows between 、range between的使用 创建数据环境 在 MySQL 中创建数据测试表 log_data: create table if not exists log_data( log_id varchar(200) comm…

能在软路由docker给部署搭建teamsperk服务器么?并且设置好ddns

参考链接(4条消息) 【个人学习总结】使用docker搭建Teamspeak服务器_blcurtain的博客-CSDN博客_teamspeak3 docker(⊙﹏⊙)哎呀,崩溃啦! (tdeh.top)TeamSpeak服务器搭建与使用 - 缘梦の镇 (cmsboy.cn)Openwrt X86 docker运行甜糖-软路由,x86系统,openwrt…

(四)K8S 安装 Nginx Ingress Controller

ingress-nginx 是 Kubernetes 的入口控制器,使用NGINX作为反向代理和负载均衡器 版本介绍 版本1:Ingress NGINX Controller(k8s社区的ingres-nginx) 以 NGINX 开源技术为基础(kubernetes.io),可在GitHub的 kubernet…

如何创建并管理一个刷题小组?

“如何收回用户对题库的使用权”,这是一个大多数题库创建人都会碰到的管理问题,也是日常咨询频繁的问题。土著刷题在v1.10版本已经上线了小组模块功能,小组拥有丰富的用户管理功能,可以管理组员对于题库的使用权进行有效的管理。咱…

高压放大器在应力波法套筒灌浆密实度检测研究中的应用

实验名称:高压放大器在应力波法套筒灌浆密实度检测研究中的应用研究方向:无损检测测试目的:钢筋套筒灌浆连接技术被广泛应用于装配式建筑节点连接中,但灌浆不密实将导致节点失效的风险。因此,施工中对套筒灌浆的密实度…

使用xca工具生成自签证书

本文使用 xca 生成自签证书。 概述 之前使用 openssl 生成证书,在 golang 中测试,发现客户端连接失败,经查发现是Subject Alternative Name不支持导致的。因虚拟机 openssl 版本较低,有个功能无法实现,且升级麻烦&…

SAP SD模块学习总结2 2023.2.27

https://www.cnblogs.com/jiangzhengjun/p/7264657.html#_Toc410466840 首先是表: VBAK: 销售订单抬头 VBAP: 销售订单项目 VBUK: 抬头状态 VBUP: 行项目状态 VBKD:销售凭证: 业务数据 VBPA: 销售凭证: 合作伙伴 VBEP:销售凭证:…

【论文速递】COLING 2022 - 带有事件论元相关性的事件因果关系抽取

【论文速递】COLING 2022 - 带有事件论元相关性的事件因果关系抽取 【论文原文】:Event Causality Extraction with Event Argument Correlations 【作者信息】:Cui, Shiyao and Sheng, Jiawei and Cong, Xin and Li, Quangang and Liu, Tingwen and S…

Android NDK动态加载SO库

背景对于一个普通的android应用来说,so库的占比通常都是巨高不下的,因为我们无可避免的在开发中遇到各种各样需要用到native的需求,所以so库的动态化可以减少极大的包体积,自从2020腾讯的bugly团队发部关于动态化so的相关文章后&a…

fuse:纠结的page下刷流程之fuse_writepage_in_flight

fuse:纠结的page下刷流程细节之fuse_writepage_in_flightfuse_writepage_in_flight硬爬代码自己理解消化作者本人如是说fuse_writepage_in_flight 先说下这个函数,位于fs/fuse/file.c,这里以4.19内核来分析。因为这个函数里面藏了很多小细节…

华为OD机试模拟题 用 C++ 实现 - 删除指定目录(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明删除指定目录题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为…

Macbook M1 安装PDI(Kettle) 9.3

Macbook M1 安装PDI(Kettle) 9.3 当前 PDI(Kettle)最新版为9.3,依赖Java JDK 11。因为没有专门用于 M1的程序,需要下载并安装x86_64架构的JDK及依赖软件,并 “强制在Intel模式下运行shell” 的方式来实现 Kettle 的正…

骨传导蓝牙耳机排行,盘点几款性能不错的骨传导耳机

随着蓝牙耳机的普及,骨传导耳机也越来越受到欢迎,很多人也都开始在了解并尝试骨传导耳机。相比于其他类型耳机,在舒适度、安全方面有一定优势。尤其是在户外运动时,或者长时间佩戴运动时,使用骨传导耳机可以避免耳朵因…

从“入门”到“专家”,一份3000字完整的性能测试体系的知识分享

随着科技的飞速发展,软件产品广泛应用于各个行业领域,人们对计算机和网络的依赖性越来越大,对新奇事物也越来越感兴趣,成千上万的用户活跃在庞大的网络系统中,这给提供服务的系统带来严重的负荷,"高并…