RPC 框架 Kitex 实践入门:性能测试指南_ 字节跳动技术团队的博客-程序员宅基地

技术标签: python  java  编程语言  人工智能  数据库  

2021 年 9 月 8 日,字节跳动宣布正式开源 CloudWeGo。CloudWeGo 是一套字节跳动内部微服务中间件集合,具备高性能、强扩展性和稳定性的特点,专注于解决微服务通信与治理的难题,满足不同业务在不同场景的诉求。CloudWeGo 第一批开源了四个项目:Kitex、Netpoll、Thriftgo 和 netpoll-http2,以 RPC 框架 Kitex 和网络库 Netpoll 为主。

日前,字节跳动服务框架团队正式开源 CloudWeGo,在抖音、今日头条均有深度应用的 Golang 微服务 RPC 框架 Kitex 也包含在其中。

本文旨在分享开发者在压测 Kitex 时需要了解的场景和技术问题。这些建议有助于用户更好地结合真实 RPC 场景对 Kitex 进行调优,使之更贴合业务需要、发挥最佳性能。用户也可以参考官方提供的压测项目 kitex-benchmark[4]了解更多细节。

微服务场景的特点

Kitex 诞生于字节跳动大规模微服务架构实践,面向的场景自然是微服务场景,因此下面会先介绍微服务的特点,方便开发者深入理解 Kitex 在其中的设计思考。

  • RPC 通信模型

微服务间的通信通常以 PingPong 模型为主,所以除了常规的吞吐性能指标外,每次 RPC 的平均时延也是开发者需要考虑的点。

  • 复杂的调用链路

一次 RPC 调用往往需要多个微服务协作完成,而下游服务又会有其自身依赖,所以整个调用链路会是一个复杂的网状结构。

在这种复杂调用关系中,某个中间节点出现的延迟波动可能会传导到整个链路上,导致整体超时。当链路上的节点足够多时,即便每个节点的波动概率很低,最终汇聚到链路上的超时概率也会被放大。所以单一服务的延迟波动 —— 即 P99 延迟指标,也是一个会对线上服务产生重大影响的关键指标。

  • 包体积大小

虽然一个服务通信包的大小取决于实际业务场景,但在字节跳动的内部统计中,我们发现线上请求大多以小包(<2KB)为主,所以在兼顾大包场景的同时,也重点优化了小包场景下的性能。

针对微服务场景进行压测

确定压测对象

衡量一个 RPC 框架的性能需要从两个视角分别去思考:Client 视角与 Server 视角。在大规模的业务架构中,上游 Client 不见得使用的也是下游的框架,而开发者调用的下游服务也同样如此,如果再考虑到 Service Mesh 的情况就更复杂了。

一些压测项目通常会把 Client 和 Server 进程混部进行压测,然后得出整个框架的性能数据,这其实和线上实际运行情况很可能是不符的。

如果要压测 Server,应该给 Client 尽可能多的资源,把 Server 压到极限,反之亦然。如果 Client 和 Server 都只给了 4 核 CPU 进行压测,会导致开发者无法判断最终得出来的性能数据是哪个视角下的,更无法给线上服务做实际的参考。

对齐连接模型

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

  • 短连接:每次请求都创建新连接,得到返回后立即关闭连接

  • 长连接池:单个连接同时只能处理一次完整请求与返回

  • 连接多路复用:单个连接可以同时异步处理多个请求与返回

每类连接模型没有绝对好坏,取决于实际使用场景。连接多路复用虽然一般来说性能相对最好,但应用上必须依赖协议能够支持包序列号,且一些老框架服务可能也并不支持多路复用的方式调用。

Kitex 最早为保证最大程度的兼容性,在 Client 端默认使用了短连接,而其他主流开源框架默认使用连接多路复用,这导致一些用户在使用默认配置压测时,出现了比较大的性能数据偏差。

后来为了契合开源用户的常规使用场景,Kitex 在 v0.0.2 中也加入了默认使用长连接的设置。

对齐序列化方式

对于 RPC 框架来说,不考虑服务治理的话,计算开销主要都集中在序列化与反序列化中。

Kitex 对于 Protobuf 的序列化使用的是官方的 Protobuf 库[6],对于 Thrift 的序列化,则专门进行了性能优化,这方面的内容在官网博客中有介绍。

当前开源框架大多优先支持 Protobuf,而部分框架内置使用的 Protobuf 其实是做了许多性能优化的 gogo/protobuf 版本,但由于 gogo/protobuf 当前有失去维护的风险,所以出于可维护性角度考虑,我们依然决定只使用官方的 Protobuf 库,当然后续我们也会计划对 Protobuf 进行优化。

使用独占 CPU

虽然线上应用通常是多个进程共享 CPU,但在压测场景下,Client 与 Server 进程都处于极端繁忙的状况,如果同时还共享 CPU 会导致大量上下文切换,从而使得数据缺乏可参考性,且容易产生前后很大波动。

所以我们建议是将 Client 与 Server 进程隔离在不同 CPU 或者不同独占机器上进行。如果还想要进一步避免其他进程产生影响,可以再加上 nice -n -20 命令调高压测进程的调度优先级。

另外如果条件允许,相比云平台虚拟机,使用真实物理机会使得测试结果更加严谨与具备可复现性。

性能数据参考

在满足上述要求的前提下,我们对多个框架使用 Protobuf 进行了压测对比,压测代码在 kitex-benchmark 仓库。在充分压满 Server 的目标下,Kitex 在连接池模式下的 P99 Latency 在所有框架中最低。而在多路复用模式下,Kitex 在各指标上也都具有更加明显的优势。

配置:

  • Client 16 CPUs,Server 4 CPUs

  • 1KB 请求大小,Echo 场景

参考数据:

  • KITEX:连接池模式(默认模式)

  • KITEX-MUX:多路复用模式

  • 其他框架均使用多路复用模式

e4487fcb78cbec3dc3d57f89d9d77092.png 6f5cbad077987c2121d5ac8cbf7cb9ac.png

结语

在当前主流的 Golang 开源 RPC 框架中,每个框架其实在设计目标上都各有侧重:有些框架侧重于通用性,有些侧重于类似 Redis 这种轻业务逻辑的场景,有些侧重于吞吐性能,而有些则更侧重 P99 时延。

字节跳动的业务在日常迭代中,常常会出现因某个 feature 导致一个指标上升,另一个指标下降的情况,因此 Kitex 在设计之初就更倾向于解决大规模微服务场景下各种问题。

Kitex 发布后,我们接到了大量来自用户的自测数据,感谢社区对我们的关注和支持,也欢迎广大开发者基于本文提供的测试指南,针对自己的实际场景选择合适的工具。更多问题,请在 GitHub 上提 Issue 交流。

相关链接

  • [1] CloudWeGo 官网:

    https://www.cloudwego.io

  • [2] Kitex:

    https://github.com/cloudwego/kitex

  • [3] Netpoll:

    https://github.com/cloudwego/netpoll

  • [4] kitex-benchmark:

    https://github.com/cloudwego/kitex-benchmark

  • [5] netpoll-benchmark:

    https://github.com/cloudwego/netpoll-benchmark

  • [6] 官方 Protobuf 库:

    https://github.com/golang/protobuf

  • [7] Thriftgo:

    https://github.com/cloudwego/thriftgo

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ByteDanceTech/article/details/121528649

智能推荐

vue elementUI tree树形控件选中子节点,获取父节点id_a913396的博客-程序员宅基地

https://blog.csdn.net/qq_37588752/article/details/80075551修改方法里的判断: if ((child.checked || child.indeterminate) &amp;&amp; (!leafOnly || leafOnly &amp;&amp; child.isLeaf)) { checkedNodes.push(child.data); }

MyBatis 条件判断 if-else 写法_铁汉柔情li的博客-程序员宅基地

mybatis 中没有if-else 写法 要用chose when otherwise 代替代码实例&lt;select id="findActiveBlogLike" resultType="Blog"&gt; SELECT * FROM BLOG WHERE state = ‘ACTIVE’ &lt;choose&gt; &lt;when te...

SQL Server 变更数据捕获(CDC)_pursuer_chen的博客-程序员宅基地

标签:SQL SERVER/MSSQL SERVER/数据库/DBA/字段/对象更改概述  变更数据捕获用于捕获应用到 SQL Server 表中的插入、更新和删除活动,并以易于使用的关系格式提供这些变更的详细信息。变更数据捕获所使用的更改表中包含镜像所跟踪源表列结构的列,同时还包含了解所发生的变更所需的元数据。对表开启了变更捕获之后,对该表的所有DML和DDL操作都会被记录,

稳定性同位素示踪技术和放射性同位素示踪技术的研究进展_齐岳生物科技在线的博客-程序员宅基地_稳定性同位素和放射性同位素区别

稳定性同位素示踪技术和放射性同位素示踪技术的研究进展同位素示踪所利用的放射性核素或稳定性核素及它们的化合物,与自然界存在的相应普通元素及其化合物之间的化学性质和生物学性质是相同的,只是具有不同的核物理性质。因此,就可以用同位素作为一种标记,制成含有同位素的标记化合物(如标记食物,药物和代谢物质等)代替相应的非标记化合物。利用放射性同位素不断地放出特征射线的核物理性质,就可以用核探测器随时追踪它在体内或体外的位置、数量及其转变等,稳定性同位素虽然不释放射线,但可以利用它与普通相应同位素的质量之...

随便推点

改变elementUI的menu菜单纵向一直保持展开样式 vue + webpack打包项目修改elementUI的源码_a_grain_of_wheat的博客-程序员宅基地_element导航菜单

最近做一个后台管理系统,需要左侧的菜单导航栏一直保持展开样式,使用的是vue+eleementUI1、使用default-openeds将从后台获取来的导航数据全部展开,2、修改menu的源码将点击一级目录的闭合打开功能注释掉。首先需要先下载下来elementUi的源码在本地,我是直接下来的压缩包,在本地,然后运行npm install命令,之后再测试一下运行npm run dist在文件夹中找到 源码文件夹element-dev/element_ui/packages/menu/src

数字通信原理的几个理解_benshong的博客-程序员宅基地_结合深度学习,谈一下对数字通信的理解

今天Dong Xuan老师自掏腰包给我们开party,真是意外惊喜,他真是一个很好的老师,令人钦佩!顺便和解理的Chao哥请教了通信原理,终于搞清楚了一些基本概念1. 计算机内的二进制信号,经过载波调制(调相,调幅,调频等),转换到一个中频模拟信号,经由高频射频模块发送出去。2.接收方首先将天线收到的模拟信号经过低通滤波器,恢复到中频信号,在经过一个模拟信号判决模块,映射到对应

ubuntu 查看java安装包的位置_ShyBoy天天向上的博客-程序员宅基地

[email protected]:~$ which java/usr/bin/[email protected]:~$ cd /usr/bin/[email protected]:/usr/bin$ ll javalrwxrwxrwx 1 root root 22 4月 11 18:31 java -> /etc/alternatives/java*[email protected]:/usr/bin$ cd /etc/alternati

跟随小破站学习java web第十五天_Mars_LJ的博客-程序员宅基地

file_upload.jsp&lt;%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%&gt;&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;&lt;html&gt;&lt;h...

POJ-3087 Shuffle'm Up 解题报告_angle555945的博客-程序员宅基地

DescriptionA common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of poker chips, S1 and S2, each stack contain

Advanced Installer读取注册表时将Program Files读取为Program Files (x86)的解决办法_H_MZ的博客-程序员宅基地

原文:Advanced Installer读取注册表时将Program Files读取为Program Files (x86)的解决办法 今天同事在做安装包的时候,有一个读取注册表路径的需求,需要根据读取的值来写配置文件,按照常规的做法,写好了注册表搜索方法,但是在测试的时候,发现总是会将系统盘下的Program Files\xxx路径读取为Program Files (x86)...

推荐文章

热门文章

相关标签