文章导读
本文主要介绍了流量录制与回放技术在压测场景下的应用。通过阅读本篇文章,你将了解到开源的录制工具如何与内部系统集成、如何进行二次开发以支持 Dubbo 流量录制、怎样通过 Java 类加载机制解决 jar 包版本冲突问题、以及流量录制在自动化测试场景下的应用与价值等。文章共约 1.4 万字,配图17张。本篇文章是对我个人过去一年所负责的工作的总结,里面涉及到了很多技术点,个人从中学到了很多东西,也希望这篇文章能让大家有所收获。当然个人能力有限,文中不妥之处也欢迎大家指教。具体章节安排如下:
1. 前言
本篇文章记录和总结了自己过去一年所主导的项目——流量录制与回放,该项目主要用于为业务团队提供压测服务。作为项目负责人,我承担了约 70% 的工作,所以这个项目承载了自己很多的记忆。从需求提出、技术调研、选型验证、问题处置、方案设计、两周内上线最小可用系统、推广使用、支持年中/终全链路压测、迭代优化、支持 dubbo 流量录制、到新场景落地产生价值。这里列举每一项自己都深度参与了,因此也从中学习到了很多东西。包含但不限于 go 语言、网络知识、Dubbo 协议细节,以及 Java 类加载机制等。除此之外,项目所产生的价值也让自己很欣喜。项目上线一年,帮助业务线发现了十几个性能问题,帮助中间件团队发现了基础组件多个严重的问题。总的来说,这个项目对于我个人来说具有非凡意义,受益良多。这里把过去一年的项目经历记录下来,做个总结。本篇文章着重讲实现思路,不会贴太多代码,有兴趣的朋友可以根据思路自己定制一套。好了,下面开始正文吧。
2. 项目背景
项目的出现源自业务团队的一个诉求——使用线上真实的流量进行压测,使压测更为“真实”一些。之所以业务团队觉得使用老的压测平台(基于 Jmeter 实现)不真实,是因为压测数据的多样性不足,对代码的覆盖度不够。常规压测任务通常都是对应用的 TOP 30 接口进行压测,如果人工去完善这些接口的压测数据,成本是会非常高的。基于这个需求,我们调研了一些工具,并最终选择了 Go 语言编写的 GoReplay 作为流量录制和回放工具。至于为什么选择这个工具,接下来聊聊。
3. 技术选型与验证
3.1 技术选型
一开始选型的时候,经验不足,并没有考虑太多因素,只从功能性和知名度两个维度进行了调研。首先功能上一定要能满足我们的需求,比如具备流量过滤功能,这样可以按需录制指定接口。其次,候选项最好有大厂背书,github 上有很多 star。根据这两个要求,选出了如下几个工具:
图1:技术选型
第一个是选型是阿里开源的工具,全称是 jvm-sandbox-repeater,这个工具其实是基于 JVM-Sandbox 实现的。原理上,工具通过字节码增强的形式,对目标接口进行拦截,以获取接口参数和返回值,效果等价于 AOP 中的环绕通知 (Around advice)。
第二个选型是 GoReplay,基于 Go 语言实现。底层依赖 pcap 库提供流量录制能力。著名的 tcpdump 也依赖于 pcap 库,所以可以把 GoReplay 看成极简版的 tcpdump,因为其支持的协议很单一,只支持录制 http 流量。
第三个选型是 Nginx 的流量镜像模块 ngx_http_mirror_module,基于这个模块,可以将流量镜像到一台机器上,实现流量录制。
第四个选型是阿里云云效里的子产品——双引擎回归测试平台,从名字上可以看出来,这个系统是为回归测试开发的。而我们需求是做压测,所以这个服务里的很多功能我们用不到。
经过比较筛选后,我们选择了 GoReplay 作为流量录制工具。在分析 GoReplay 优缺点之前,先来分析下其他几个工具存在的问题。
- jvm-sandbox-repeater 这个插件底层基于 JVM-Sandbox 实现,使用时需要把两个项目的代码都加载到目标应用内,对应用运行时环境有侵入。如果两个项目代码存在问题,造成类似 OOM 这种问题,会对目标应用造成很大大的影响。另外因为方向小众,导致 JVM-Sandbox 应用并不是很广泛,社区活跃度较低。因此我们担心出现问题官方无法及时修复,所以这个选型待定。
- ngx_http_mirror_module 看起来是个不错的选择,出生“名门”。但问题也有一些。首先只能支持 http 流量,而我们以后一定会支持 dubbo 流量录制。其次这个插件要把请求镜像一份出去,势必要消耗机器的 TCP 连接数、网络带宽等资源。考虑到我们的流量录制会持续运行在网关上,所以这些资源消耗一定要考虑。最后,这个模块没法做到对指定接口进行镜像,且镜像功能开关需要修改 nginx 配置实现。线上的配置是不可能,尤其是网关这种核心应用的配置是不能随便改动的。综合这些因素,这个选型也被放弃了。
- 阿里云的引擎回归测试平台在我们调研时,自身的功能也在打磨,用起来挺麻烦的。其次这个产品属于云效的子产品,不单独出售。另外这个产品主要还是用于回归测试的,与我们的场景存在较大偏差,所以也放弃了。
接着来说一下 GoReplay 的优缺点,先说优点:
- 单体程序,除了 pcap 库,没有其他依赖,也无需配置,所以环境准备很简单
- 本身是个可执行程序,可直接运行,很轻量。只要传入合适的参数就能录制,易使用
- github 上的 star 数较多,知名度较大,且社区活跃
- 支持流量过滤功能、按倍速回放功能、回放时改写接口参数等功能,功能上贴合我们的需求
- 资源消耗小,不侵入业务应用 JVM 运行时环境,对目标应用影响较小
对于以 Java 技术栈为基础的公司来说,GoReplay 由于是 Go 语言开发的,技术栈差异很大,日后的维护和拓展是个大问题。所以单凭这一点,淘汰掉这个选型也是很正常的。但由于其优点也相对突出,综合其他选型的优缺点考虑后,我们最终还是选择了 GoReplay 作为最终的选型。最后大家可能会疑惑,为啥不选择 tcpdump。原因有两点,我们的需求比较少,用 tcpdump 有种大炮打蚊子的感觉。另一方面,tcpdump 给我们的感觉是太复杂了,驾驭不住(流下了没有技术的眼泪