https://maimai.cn/article/detail?fid=1767401397&efid=R2_kM5y-yEUDCK88FZWrGA
干货不迷路2021 年 9 月 8 日,字节跳动宣布正式开源 CloudWeGo。CloudWeGo 是一套字节跳动内部微服务中间件集合,具备高性能、强扩展性和稳定性的特点,专注于解决微服务通信与治理的难题,满足不同业务在不同场景的诉求。2022 年 6 月 21 日,Hertz 正式开源。Hertz 链接:http://github.com/cloudwego/hertz,欢迎大家共同参与建设^_^

日前,CloudWeGo 团队正式开源字节跳动最大的 HTTP 框架 Hertz。Hertz 在发布之后得到了大量用户的关注,开源四个月以来,Hertz 已经收获了 2k+ star。有很多用户自己进行了测试,感谢社区对我们的关注和支持。

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

1. 微服务 HTTP 场景的特点

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

  • HTTP 通信模型

微服务间的通信通常以 Ping-Pong 模型为主,除了常规的吞吐性能指标外,每次 HTTP 的平均时延也是开发者需要考虑的点。吞吐达到瓶颈时可以通过增加机器快速解决,但对用户使用体验有显著影响的时延却没有那么容易降低。在微服务场景下,一次调用往往需要多个微服务协作完成,即使每个节点延迟很低,最终汇聚到链路上的时延也会被放大,因此微服务场景下时延指标是开发者更应该关注的点。Hertz 在保证吞吐的前提下,也针对时延做了一定优化。

  • 长短连接使用

由于 TCP 连接首次建立时需要三次握手,如果每个请求都建立新连接,这部分的开销是非常大的。因此对于时延敏感型服务,尽量使用长连接完成请求。在 HTTP 1.1 中,长连接也是默认的选项。但是没有银弹,维持连接也需要消耗资源,长连接的水平扩展能力也不如短连接。因此,在某些场景下并不适合使用长连接,比如定时拉取配置的场景,在这个场景下,建连时延对配置影响并不大,且当配置中心负载过高时,希望能够方便的进行水平扩容,这时短连接可能是一个更好的选择。

  • 包体积大小

一个服务的包大小取决于实际的业务场景。HTTP 场景的数据可以放在 query、path、header、div 等地方,不同位置对解析造成的影响也不一样。HTTP 的 header 是标识符协议,在没有找到特定的标识符之前,框架并不知道 header 还有多少,因此框架需要收到全部的 header 后才能够解析完成,对框架的内存模型不很友好。Hertz 也针对 header 解析做了特殊的优化,分配足够的 buffer 空间给 header,减少 header 处理时跨包拷贝的开销。

同时在字节跳动内部线上服务的统计中,发现大部分包在 1K 以内(但是太小的包没有实际意义,比如固定返回 "hello world"),同时大包场景上不封顶,各个包大小均有涉及,所以 Hertz 在最常用的 128k 以内的包的性能(吞吐和时延)进行了重点优化。

  • 并发数量

每个实例的上游可能会有很多个,不会只接受某个实例的请求;而且,HTTP 1 的连接不能够多路复用,每条连接上只能同时处理一个请求。因此 server 需要接受多个连接同时处理。不同服务的连接使用率也不同,比如压测服务的连接使用率很高,一个请求完成后马上就会进行下一个请求;有的服务连接使用率很低,虽然是长连接,但是只使用一次。这两者使用的连接模型并不相同,前者应使用 goroutine per connection 的模型减少上下文的切换,后者应使用协程池减少过多 goroutine 的调度开销。Hertz 也同时支持这两种场景,用户可以根据自己的业务场景选择合适的配置。

2. 针对 HTTP 场景进行压测

2.1 使用贴近自己的场景

Github 上的压测项目有很多,网络上也有很多性能测试报告,但是这些项目和测试不一定贴合自己。举个极端一点的例子,在真实场景中你会写一个项目无论 client 发什么 server 都只回 hello world 吗?很遗憾,很多的压测项目就是这么做的。

在进行压测前,应考虑自己真正的使用场景,比如:

  • 长短连接的使用:使用长连接还是短连接更符合自己的场景。
  • 连接使用率的估算:如果使用长连接,且连接使用率很高(大部分场景),则使用默认配置即可;如果连接使用率很低,可以添加配置:server.WithIdleTimeout(0),将 goroutine per connection 的模型修改为协程池模型,并进行对比测试。
  • 数据位置及大小的确定:上面提到不同位置(如 query、header、div 等)及大小的数据对框架可能造成影响,如果所有框架的性能都比较一般,可以考虑换一个数据传输位置。
  • 并发数的确定:有的服务属于轻业务重框架,这个时候框架的并发可能会很高;有的服务属于重业务轻框架,这个时候框架的并发可能会很低。

如果只是想看一下框架的性能,可以使用常规的场景:长连接、较高连接使用率、1k div、100 并发等。hertz-benchmark 仓库默认的压测配置也是如此。同时 hertz-benchmark 仓库也开发给用户 header、div、并发数的配置,用户可以方便的修改这些配置完成贴合自己的压测。

2.1.1 确定压测对象

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

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

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

2.1.2 使用独占 CPU

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

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

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

3. 性能数据参考

在满足上述要求的前提下,我们基于当前最新版本对多个框架进行了压测对比,压测代码在 hertz-benchmark 仓库。在充分压满 Server 的目标下,Hertz 的 P99 延迟在所有压测框架中最低,吞吐也是属于第一梯队,且在持续优化中。

  • CPU: AMD EPYC 7Y83 64-Core Processor 2.7GHz

    • 运行限定 server 4-CPUs,client 16-CPUs

  • OS:Debian GNU/Linux 10 (buster)
  • Go 1.19
  • hertz v0.3.2,fasthttp v1.40.0,gin v1.8.1,fiber v2.38.1

四个框架的吞吐和时延比较

三个框架的吞吐和时延比较

4. 结语

Hertz 作为一个超大规模企业级的微服务 HTTP 框架,其在设计之初就更倾向于解决大规模微服务场景下的各种问题。在推广过程中也遇到了各种各样的服务,踩了各种各样的坑,也是基于这些服务和遇到的问题写了本文。欢迎广大开发者基于本文提供的测试指南,针对自己的实际场景选择合适的工具。更多问题,请在 GitHub 上提 Issue 交流。

相关链接

[1] hertz-benchmark: http://github.com/cloudwego/hertz-benchmark

[转帖]HTTP 框架 Hertz 实践入门:性能测试指南的更多相关文章

  1. 《深度学习框架PyTorch:入门与实践》的Loss函数构建代码运行问题

    在学习陈云的教程<深度学习框架PyTorch:入门与实践>的损失函数构建时代码如下: 可我运行如下代码: output = net(input) target = Variable(t.a ...

  2. Quartz应用实践入门案例二(基于java工程)

    在web应用程序中添加定时任务,Quartz的简单介绍可以参看博文<Quartz应用实践入门案例一(基于Web应用)> .其实一旦学会了如何应用开源框架就应该很容易将这中框架应用与自己的任 ...

  3. Quartz应用实践入门案例一(基于Web环境)

    Quartz是一个完全由java编写的开源作业调度框架,正是因为这个框架整合了许多额外的功能,所以在使用上就显得相当容易.只是需要简单的配置一下就能轻松的使用任务调度了.在Quartz中,真正执行的j ...

  4. 无锁并发框架Disruptor学习入门

    刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...

  5. .NET轻量级MVC框架:Nancy入门教程(二)——Nancy和MVC的简单对比

    在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy的优势在哪里?和微软的MVC比 ...

  6. 【军哥谈CI框架】之入门教程之第二讲:分析CI结构和CI是怎么工作的

    [军哥谈CI框架]之入门教程之第二讲:分析CI结构和CI是怎么工作的   之入门教程之第二讲:分析CI结构和CI是如何工作的大家好!上一节,我们共同部署了一个CI网站,做到这一点非常简单,但是,亲们, ...

  7. 掌握Tiles 框架 (一)---Tiles入门和Tiles 框架和体系结构

    掌握Tiles 框架 (一)---Tiles入门和Tiles 框架和体系结构 入门 本教程所讲述的内容 本教程讲述如何使用 Tiles 框架来创建可重用的表示组件.(在最初创建它时,Tiles 框架被 ...

  8. IOC框架Ninject实践总结

    原文地址:http://www.cnblogs.com/jeffwongishandsome/archive/2012/04/15/2450462.html IOC框架Ninject实践总结 一.控制 ...

  9. WCF宿主实践入门

    本篇属于WCF实践入门,由于博主本人水平有限,没有理论上的介绍,仅仅从其几种不同的宿主方式分别介绍WCF的使用. WCF有多种宿主方式:1.自托管宿主,2.windows service宿主,3.II ...

  10. Google C++测试框架系列:入门

    Google C++测试框架系列:入门 原始链接:V1_6_Primer 注 GTest或者Google Test: Google的C++测试框架. Test Fixtures: 这个词实在找不到对应 ...

随机推荐

  1. 9、线性布局(Row和Column)

    自定义的IconContainer void main() { runApp(MaterialApp( theme: ThemeData(primarySwatch: Colors.yellow), ...

  2. 非暴力拆解:小熊派NB-IoT通信扩展板

    摘要:相信大家对小熊派的NB-IoT通信扩展板已经非常了解了,但你有真正的了解过其内部构造吗?今天小编不聊技术,带你做一回拆·机·客! 相信大家对小熊派的NB-IoT通信扩展板已经非常了解了,但你有真 ...

  3. Seal 软件供应链防火墙 v0.2 发布,提供依赖项全局洞察

    Seal 软件供应链防火墙 v0.2 已于近日发布.这款产品旨在为企业提供代码安全.构建安全.依赖项安全及运行环境安全等4大防护,通过全链路扫描.问题关联及风险组织的方式保护企业软件供应链安全,降低企 ...

  4. 火山引擎 DataTester 科普:A/B 实验常见名词解释

    DataTester 是字节跳动在 2019 年正式通过火山引擎数智平台推出的对外服务的 A/B 实验工具,它基于先进的底层算法,提供科学分流能力,提供智能的统计引擎,实验结果可靠有效,助力业务决策. ...

  5. 【django-vue】登录注册模态框分析 登录注册前端页面 腾讯短信功能二次封装 短信验证码接口 短信登录接口 短信注册接口

    目录 昨日回顾 csrf跨站请求伪造 接口幂等性 异常捕获 今日内容 1 登录注册模态框分析 Login.vue Header.vue 2 登录注册前端页面复制 2.0 Header.vue 2.1 ...

  6. RabbitMQ--工作模式

    单一模式 即单机不做集群 普通模式 即默认模式,对于消息队列载体,消息实体只存在某个节点中,每个节点仅有 相同的元数据,即队列的结构 当消息进入A节点的消息队列载体后,消费 者从B节点消费时,rabb ...

  7. Mina Tcp服务器开发

    因项目架构需求,需要开发一个Mina Tcp服务器.我的Mina服务器是Java winForm,这与在web项目使用会有少许不同. 1.Maven依赖 <dependency> < ...

  8. 3.1 《数据库系统概论》SQL概述及数据定义(模式SCHEMA、表TABLE、索引INDEX)

    前言 本篇文章学习书籍:<数据库系统概论>第5版 王珊 萨师煊编著 视频资源来自:数据库系统概论完整版(基础篇+高级篇+新技术篇) 由于 BitHachi 学长已经系统的整理过本书了,我在 ...

  9. nvm:npm的包管理器

    NVM: npm的包管理器 其实许久前就像写这个模块了,只是之前使用后又搁置了,今天下项目时node版本不一致,才想起记录 nvm下载地址: Releases · coreybutler/nvm-wi ...

  10. java读取解析endnote文件

    有些项目中会要求代码解析endnote文献资料获取一些标准的信息,例如XX在某著名期刊上发表了某篇文章,关于发表文章的这个事情的描述就会给坐着一个endnote文件来记录文章名称.作者.期刊名称.出版 ...