前言
迄今为止,软件测试的发展一共经历了五个重要时期:
- 1957年之前-调试为主(Debugging Oriented)
- 1957–1978-证明为主(Demonstration Oriented)
- 1979–1982-破坏为主(Destruction Oriented)
- 1983–1987-评估为主(Evaluation Oriented)
- 1988–至今-预防为主(Prevention Oriented)
——出自 Dave Gelperin和William C. Hetzel 的《THE GROWTH OF SOFTWARE TESTING》。
尽管软件测试的每一个发展阶段都不可避免地受限于当时的认识水平,但先驱者们始终秉持着对知识的渴望与探索,不断回顾并提炼前辈们的智慧结晶,勇于开创性地提出新颖的理论与探索方向。这种持续进取、勇于创新的精神,不仅是对专业深度的追求,更是对人类智慧传承的崇高致敬,值得我们每个人深深敬仰并努力学习。正如古语所云:“以铜为鉴,可以正衣冠;以人为鉴,可以明得失;以史为鉴,可以知兴替。”通过深刻理解软件测试的演进历程,我们不仅能够清晰把握其来龙去脉,更能从中汲取力量,明确未来发展的方向,确保我们的步伐既稳健又充满远见。
基本概念
流量回放是一种测试技术,用于模拟实际生产环境中的网络流量,并将其重新发送到系统或应用程序中。这一过程允许测试人员重现特定时间段内的网络流量,以评估系统在不同负载和情况下的性能、稳定性和可靠性。
流量回放的基本思想比较简单,正如上图所示测试数据不再由人为制造,而是直接复制线上的流量数据。
为了提升测试效率和质量,我们采取了一种创新的策略,即将部分线上流量复制并导向至被测集群中,模拟真实的线上环境进行自动化测试回放。这一过程不仅实现了测试数据的即时捕获与重用,解决了传统测试中数据构造复杂且难以全面覆盖的难题,还省去了繁琐的自动化脚本编写与维护工作。
通过将这些真实流量沉淀为可复用的测试用例,我们确保了测试场景的丰富性和真实性,能够自动覆盖更多潜在的业务逻辑路径,有效提升代码覆盖率。这种方式不仅减轻了测试人员的工作负担,还显著增强了测试的全面性和有效性,有效降低了因测试不全面而导致的漏测风险。
当然,我们也充分认识到线上与线下环境之间存在的差异,如权限验证、缓存机制等,这些差异可能会影响到回放测试的执行效果。为此,我们制定了一系列针对性的回放策略,旨在克服这些环境差异带来的挑战,确保测试回放能够顺利进行,从而最大化地发挥流量回放测试的价值。
流量回放的优势
流量回放作为一种流行的软件技术,具有如下优点:
1. 高度模拟真实环境:
流量回放能够捕获并重现生产环境中的实际网络流量,这意味着测试环境能够非常接近甚至等同于生产环境。这种高度的模拟性使得测试更加准确和可靠。
2. 提高测试覆盖率:
通过捕获并回放各种类型的流量,包括正常请求、异常请求、高并发请求等,流量回放可以显著提高测试的覆盖率。这有助于发现那些在正常操作中可能难以触发的潜在问题。
暂时无法在飞书文档外展示此内容
3. 快速定位和复现问题:
当生产环境出现问题时,流量回放可以帮助快速定位和复现问题。通过回放导致问题的流量,测试人员可以更容易地找到问题的根源,并验证修复措施的有效性。
4. 减少测试时间和成本:
由于流量回放可以模拟实际生产环境的流量,因此可以减少在测试环境中模拟这些流量的时间和成本。此外,通过自动化回放流量,还可以进一步提高测试效率。
5. 支持持续集成和持续部署(CI/CD):
在CI/CD流程中,流量回放可以作为一个重要的测试环节,确保每次代码变更后系统都能正确处理各种流量。这有助于保持系统的稳定性和可靠性。
6. 增强安全性测试:
通过模拟恶意攻击或异常流量,流量回放可以帮助测试系统对安全威胁的防御能力。这有助于及早发现潜在的安全漏洞,并采取相应的防护措施。
7. 支持多场景测试:
流量回放不仅限于单个场景或请求,还可以回放整个会话或用户行为序列。这使得测试人员能够更全面地评估系统在不同场景下的性能和稳定性。
8. 数据驱动的测试:
流量回放依赖于实际生产数据,这使得测试更加数据驱动。测试人员可以根据实际数据调整测试策略,以更准确地反映系统的真实表现。
9. 提高团队协作效率:
通过共享流量回放数据,不同团队(如开发、测试、运维等)可以更加紧密地协作。这有助于减少沟通成本,提高问题解决的效率。
10. 易于集成和扩展:
流量回放工具通常具有良好的可扩展性和集成性,可以轻松地与其他测试工具和系统集成。这使得流量回放技术可以灵活地应用于各种测试场景和需求中。
方案比较
1. Nginx层流量复制
工作原理: Nginx层流量复制主要依赖于Nginx的ngx_http_mirror_module模块(Nginx版本 > 1.13.4)。该模块允许将线上实时流量镜像至其他环境,而Nginx最终会丢弃mirror的响应,从而不影响源站请求的响应。通过配置mirror指令,可以指定将哪些请求镜像到哪个后端服务器。
应用场景:
- 验证新功能或服务的性能与稳定性,而不影响线上环境。
- 排查线上问题,通过镜像流量到测试环境进行复现。
- 服务重构后的测试,确保新旧版本兼容。
优缺点: - 优点:实现简单,配置灵活,对线上服务无影响。
- 缺点:受限于Nginx的配置和版本,且只能复制HTTP流量。
2. 基于业务代码层的引流
工作原理: 这种方式通常通过修改业务代码来实现,例如在关键的业务处理逻辑中插入额外的代码,将部分请求转发到另一个系统或环境。这可以通过各种编程语言的网络请求库(如Python的requests、Java的HttpClient等)来实现。
应用场景:
- 复杂的业务逻辑测试,需要精确控制哪些请求被转发。
- 跨系统、跨服务的流量调度与负载均衡。
优缺点: - 优点:灵活性强,可以根据业务需求进行精确控制。
- 缺点:需要修改业务代码,可能增加系统复杂度和维护成本。
3. 基于访问日志回放
工作原理: 首先,收集生产环境的访问日志(如Nginx的access log)。然后,通过工具或脚本解析这些日志,模拟出原始的HTTP请求,并将这些请求发送到测试环境。
应用场景:
- 验证测试环境与生产环境的一致性。
- 回放特定时间段的流量,用于性能测试或故障复现。
优缺点: - 优点:能够精确模拟生产环境的请求,便于问题复现和性能测试。
- 缺点:需要处理大量的日志数据,且可能无法完全模拟复杂的网络环境和并发情况。
4. 基于TCP/IP层的引流
工作原理: 在TCP/IP层面进行流量复制,通常需要使用专门的网络工具或设备(如tcpcopy、Throwing Star LAN Tap等)。这些工具可以捕获经过网络接口的TCP/IP数据包,并将其复制到另一个网络接口或服务器。
应用场景:
- 跨网络环境的流量复制,如从生产网络复制到测试网络。
- 网络性能监控与故障排查。
优缺点: - 优点:能够捕获并复制所有经过网络接口的TCP/IP流量,包括非HTTP协议的数据。
- 缺点:配置复杂,可能需要专业的网络知识和设备支持。
综上所述,这四种流量回放方式各有优缺点,适用于不同的应用场景和需求。在实际应用中,可以根据具体情况选择最合适的方式。
主要用途
- 性能测试:评估系统在正常负载下的性能指标,如吞吐量、响应时间等。
- 压力测试:模拟高负载情况下的流量,测试系统在压力下的表现和稳定性。
- 安全测试:模拟恶意攻击或异常情况下的流量,评估系统对安全威胁的防御能力。
- 功能测试:验证系统是否正确处理各种类型的请求和响应,确保系统功能的完整性和正确性。
- 服务架构升级:在升级服务架构后,通过流量回放回归测试原有系统功能,确保系统稳定运行。
- 复杂业务场景:面对复杂度高的业务场景,通过流量回放进行迭代版本的回归测试,减少测试时间和成本。
- 自动化测试补充:自动化测试可能无法覆盖所有复杂场景,流量回放可以作为补充,提高测试覆盖率和质量
实现方式
确实,随着流量回放技术的发展,不同层面和架构的解决方案应运而生,每种方案都有其独特的优势和应用场景。下面我将分别介绍您提到的几种前沿的流量回放工具和框架:GoReplay、Diffy、jvm-sandbox-repeater,以及基于Service Mesh的流量回放技术,并简要阐述它们的原理、实现方式及应用方式。
1.GoReplay + Diffy
1.1 GoReplay
基础知识了解
原理: GoReplay是一个开源的网络工具,工作在TCP/IP层,能够捕获生产环境中的HTTP/HTTPS流量,并将其转发到测试或开发环境。它支持对流量进行编辑、修改、过滤等操作,以便更灵活地模拟不同的测试场景。goreplay 前称是 gor,主要用 Go 语言编写。
实现方式:
- 捕获流量:通过监听指定端口的网络流量,捕获HTTP/HTTPS请求和响应。
- 处理流量:提供丰富的中间件(middleware)来编辑、修改、过滤捕获到的流量。
- 回放流量:将处理后的流量转发到指定的目标服务器。
应用方式: GoReplay非常适合用于性能测试、压力测试以及安全测试等场景,能够轻松模拟生产环境中的真实流量。
git地址:github地址
主要功能简要介绍如下:
- 支持流量的放大和缩小,以及频率限制;
- 支持根据正则表达式过滤流量,以便单独测试某个(或某些)服务;
- 支持修改HTTP请求头,比如替换User-Agent或者增加某些HTTPHeader;
- 支持将请求记录到文件中,以备回放和分析;
- 支持与外部系统集成,比如与ElasticSearch集成,存入流量并进行实时分析。
详细原理剖析:
GoReplay一般被部署至两处:一处作为监听部分,通常被部署在生产环境中,用于录制流量;另一处作为回放部分,通常被部署在测试环境或预发环境中,用于回放流量。录制的流量可以被分发到多个环境中进行回放,也可以以不同的速率进行回放。
入上图:
- client为线上环境的线上用户 访问线上service完成最基本的业务访问与应答。
- service为线上服务
- Capture network 为流量focpy模块,底下虚线部分为其具体实现原理
- Filter 过滤器:
- 功能描述:
过滤器用于对录制的流量进行筛选,只保留符合特定条件的请求或响应。这有助于减少不需要的流量数据,提高分析或测试的效率和准确性。 - 工作方式:
- GoReplay的过滤器可以基于URL、HTTP头、HTTP方法等多种条件进行配置。
- 当流量通过GoReplay时,过滤器会根据预设的规则对流量进行匹配,符合条件的流量将被保留,不符合条件的流量则会被丢弃。
- 示例与配置:
在命令行中,可以使用–http-allow-url、–http-disallow-url等参数来配置URL过滤器。例如,–http-allow-url "/api/*“将只允许以”/api/"开头的URL请求通过。
- 功能描述:
- Rewrite 重写器
- 功能描述:
重写器用于对录制的流量进行修改,以符合特定的测试或分析需求。它可以更改请求或响应中的URL、HTTP头、请求体等内容。 - 工作方式:
- 重写器在流量通过GoReplay时,会根据预设的规则对流量进行修改。
- 修改后的流量将继续传递至下一个处理阶段,如回放或分析。
- 示例与配置:
GoReplay的重写功能可能不如某些代理或网关工具那样强大,但通常可以通过编写自定义的插件或中间件来实现更复杂的重写逻辑。
- 功能描述:
- Middleware 中间件:
- 功能描述:
中间件是GoReplay中用于扩展其功能的重要机制。它允许开发者在流量处理的不同阶段插入自定义的代码,以实现特定的功能,如流量过滤、修改、日志记录等。 - 工作方式:
- 中间件通常作为GoReplay处理流程中的一个环节,接收上游传递的流量数据,并可能对其进行处理或修改。
- 处理后的流量数据可以传递给下一个中间件,或直接传递给下游的处理流程。
- 示例与配置:
在GoReplay中,可以通过–middleware参数指定要使用的中间件。例如,–middleware "python3 middleware.py"将启动一个Python脚本作为中间件,该脚本可以对流量数据进行处理。
- 功能描述:
- Filter 过滤器:
- requestCopy 阶段将在筛选器、重写器、中间件 筛选处理复制出来的流量、报文 发到QA ,处理后交由后续处理阶段进行 比对、监听、分析。
gor的安装
一 、首先安装Golang及相关依赖环境 在官网上下载安装包或者go的一些中文网站上下载安装包并安装,此处略。
- https://golang.org/dl/
- https://studygolang.com/dl
二、安装gor
1、从https://github.com/buger/gor/releases 下载最新的 Gor 二进制文件
[图片]
1、直接解压 解压后的 gor文件既可直接调用的二进制文件
[root@vm-jmeter ~]# tar xvzf gor_1.3.1_x64.tar.gz
gor
gor的常用命令:
流量复制
- 基础流量复制:
gor --input-raw :80 --output-http "http://staging.com"
监听本地80端口的HTTP流量,并将其复制到http://staging.com。
- 流量过滤复制:
- 使用正则表达式过滤URL:
gor --input-raw :8080 --output-http staging.com --output-http-url-regexp ^www.
- 只允许特定HTTP方法:
gor --input-raw :80 --output-http 192.168.2.6:8000 --http-allow-method POST
- 使用正则表达式过滤URL:
- 流量放大或缩小:
- 缩小流量:
gor --input-raw :80 --output-tcp "replay.local:28020|10%"
- 放大流量(在回放时实现):
gor --input-file "requests.gor|200%" --output-http "staging.com"
- 缩小流量:
流量记录与回放
- 记录流量到文件:
- gor --input-raw :80 --output-file requests.gor:将捕获的HTTP流量记录到requests.gor文件中。
- 使用时间戳命名文件:gor --input-raw :80 --output-file %Y%m%d.log
- 从文件回放流量:
- gor --input-file “requests.gor” --output-http “staging.com”:从requests.gor文件中读取HTTP请求,并将其发送到staging.com。
- 控制回放速率:gor --input-file “requests.gor|200%” --output-http “staging.com”,以2倍速回放流量。
高级选项
- 流量分配:
- 将流量分配到多个目标:
gor --input-tcp :28020 --output-http "http://staging.com" --output-http "http://dev.com" --split-output true
- 将流量分配到多个目标:
- 调试和日志:
- 打开调试模式:
gor --debug
(注意:具体参数可能因版本而异,请参考gor --help) - 记录CPU性能分析文件:
gor --cpuprofile output.pprof
(用于性能分析)
- 打开调试模式:
- 循环和退出控制:
- 循环执行文件回放:
gor --input-file-loop --input-file "requests.gor" --output-http "staging.com"
- 设置回放时间:
gor --exit-after 30s --input-file "requests.gor" --output-http "staging.com"
- 循环执行文件回放:
GoReplay应用实践demo
首先我用有一个java服务 ,我们本次只应用/hello接口,我给此接口像工作台打印了name方便观察结果。
然后我在我的服务器上启动服务两次模拟,服务一为生产环境,服务二为测试环境
启动服务一:8881端口 充当生产环境
java -jar service-demo1-0.0.1-SNAPSHOT.jar --server.port=8881
启动服务器二:8882端口 充当测试环境
java -jar service-demo1-0.0.1-SNAPSHOT.jar --server.port=8882
好戏来了,我们开始应用GoReplay捕捉Web流量喽!
1、下列命令将监听端口8881的所有网络活动,并将其记录到stdout:
sudo ./gor --input-raw :8881 --output-stdout
从postman发起端口请求五次
“生产环境8881” 被请求了五次记录,同时 gor所在的窗口显示五次请求内容
生产环境日志
Gor get到的流量
因为我没带参数所以默认 没传name,传那么的话 流量长这样,标红的是我传的name=liwei
1 5ff322b101cb643029934fac 1722082190734429686 0
GET /hello?name=liwei HTTP/1.1
User-Agent: PostmanRuntime/7.40.0
Accept: */*
Cache-Control: no-cache
Postman-Token: 97c73daf-5334-49f2-a9bb-3f63834ea1d2
Host: www.lwmzz.cn:8881
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
2、流量转发
./gor --input-raw :8881 --output-http http://www.lwmzz.cn:8882
通过监控 8881生产环境,并同步到测试环境 8882 ,后便为啥用域名 我纯粹是像验证下使用域名会不会有bug 证明没问题。
这次我postman name=liwei68
生产环境 8881 收到后日志
测试环境 8882 收到的Gor (后面GoReplay都是用简称为Gor)流量回放转发的请求
3、流量放大
./gor --input-raw :8881 --output-http 'http://www.lwmzz.cn:8882|300%'
使用|300% 方式将流量放大三倍 ,可以用来压测、稳定性测试
4、保存流量和异步回放
有时可能无法或不需要实时回放,可将流量输出到文件
./gor --input-raw :8881 --output-file requests.log
当然也可以指定文件格式
./gor --input-raw :8881 --output-file %Y%m%d.log --output-file-append 回追加到当前日期的文件里
当想回放时
./gor --input-file requests_0.log --output-http "http://localhost:8882"
此时回读取requests_0.log 文件流量并发到测试环境 。
更多操作可以到github查看详细文档gor github链接
1.2 Diffy
原理: https://github.com/twitter-archive/diffyDiffy 是一个由Google开发的流量回放系统,它结合了流量捕获、回放和结果对比的功能。Diffy的核心在于能够精确地比较回放请求和原始请求之间的差异,以及它们对应响应之间的差异。
实现方式:
- 捕获流量:在生产环境中捕获HTTP请求和响应。
- 回放流量:在测试环境中回放捕获到的请求,并捕获相应的响应。
- 结果对比:使用差异检测算法比较原始响应和回放响应之间的差异。
应用方式: Diffy特别适用于验证服务变更(如版本升级、配置更改)是否对系统行为产生了非预期的影响。
一般来说,对于同一个请求,如果在不同环境中执行后,得到的响应体的内容是完全一致的,就可以认为验证成功;如果不一致,则不能简单得出验证失败的结论。实际情况下,会有各种各样的“噪声”影响比对的结果,例如响应体中的时间戳、自增值、随机值等,都是正常的不一致字段,我们需要将这些字段排除,否则它们就会影响验证的结果。
依靠人工设置白名单的方式进行去噪是一个先入为主的想法,但它只适合系统简单、服务接口数量不多的情况。如果系统复杂,人工成本就会直线上升。我们希望通过一种自动化的方式完成去噪的工作,在这里,我们将介绍如何通过Diffy工具进行自动化去噪。
Diffy是一款开源的测试工具,能够进行流量的比对和去噪,它的噪声识别原理非常简单,如果同一个请求在同一环境(或两个对等的环境)中,两次执行得到的响应体中的某个字段不一致,我们就认为它们是正常的不一致,将其设置为噪声。
暂时无法在飞书文档外展示此内容
Diffy作为前端代理的核心组件,其首要职责是在请求到达后端服务之前,精准地控制并分发这些请求至不同环境与版本的服务中。这一机制旨在实现两个关键目标:噪声的有效过滤与不同版本服务间执行结果的细致对比。
具体而言,Diffy首先在稳定可靠的primary环境和secondary环境中部署了经过验证的服务版本,这两个环境被用作噪声排除的基准。当一个请求同时在这两个环境中执行时,如果它们的响应结果不一致,那么这种差异很可能源于非预期因素(即噪声),而非服务本身的改变。通过比较这两个环境的结果,Diffy能够有效地识别并过滤掉这些潜在的噪声。
接下来,Diffy将请求导向candidate环境,该环境中部署了待测试的新版本服务。在此阶段,Diffy不仅执行请求,还会将candidate环境的响应结果与经过primary和secondary环境去噪后的标准响应进行对比。如果即使在排除了噪声影响后,candidate环境的响应仍然与标准响应存在差异,那么这可以被视为在新版本服务中发现了潜在的缺陷或不一致之处。
通过这样的流程,Diffy不仅为服务的持续集成与测试(CI/CD)过程提供了强有力的支持,还显著提高了发现服务缺陷的准确性和效率。
1.3 总结:
GoReplay + Diffy是一款专注于TCP/IP层面的流量捕获与回放工具,其设计初衷在于减少对应用服务层的直接介入,从而实现了低侵入性的流量复制与测试。这一特性显著降低了系统的维护成本,使得开发者和测试人员能够在不干扰生产环境的情况下,轻松地进行性能测试、故障复现及安全审计等工作。
然而,GoReplay的运作机制也带来了几个显著的局限性:
- 录制粒度限制:由于GoReplay工作在TCP/IP层,它捕获的流量数据粒度相对较粗,缺乏对应用层协议(如HTTP、HTTPS等)的深入解析和定制能力。尽管用户可以对捕获的流量进行一定程度的加工处理,但这些操作通常局限于流量的表面形式,难以针对具体的应用逻辑进行灵活调整,从而限制了其应用的广泛性和深度。
- 回放数据一致性要求高:在TCP/IP层面进行流量回放时,GoReplay对测试环境中的数据一致性有着极高的要求。如果回放环境中的数据与录制时存在差异(如数据库状态、文件系统等),则可能导致回放失败或结果不准确。这种对数据一致性的严格要求增加了测试的难度和复杂度。
- 写请求支持有限:在TCP/IP层面进行回放时,GoReplay通常不支持非幂等的写请求。这是因为写请求会改变服务器端的数据状态,而在多次回放相同请求时,由于数据状态的变化,每次回放的结果都可能不同。这种限制使得GoReplay在需要精确控制数据状态变化的场景中(如数据库更新、文件写入等)表现不佳。
综上所述,GoReplay作为一款基于TCP/IP层的流量回放工具,在提供低侵入性和低维护成本的同时,也面临着录制粒度限制、回放数据一致性要求高以及写请求支持有限等挑战。因此,在选择使用GoReplay时,用户需要根据自己的具体需求和测试场景进行权衡和选择。
2. jvm-sandbox-repeater
原理: jvm-sandbox-repeater是一个针对Java应用的流量回放工具,它工作在业务代码层,通过Java Agent技术动态地注入代码到目标应用中,以捕获和回放业务请求。
实现方式:
- Agent注入:将jvm-sandbox-repeater的Agent JAR包添加到Java应用的启动参数中,实现代码的动态注入。
- 捕获请求:在业务代码的关键位置(如Controller层)捕获请求和响应。
- 回放请求:在测试环境中模拟这些请求,并验证响应的一致性。
应用方式: jvm-sandbox-repeater特别适用于Java应用的微服务架构中,能够精确地模拟和验证服务间的调用行为。
Demo还没开发完,有时间再弄
3. 基于Service Mesh的流量回放技术
原理: 基于Service Mesh的流量回放技术利用Service Mesh的流量路由和拦截能力,在不影响业务代码的情况下实现流量的捕获、修改和回放。
实现方式:
- 部署Service Mesh:在集群中部署Istio等Service Mesh平台。
- 配置路由规则:通过Service Mesh的配置文件(如Istio的VirtualService和DestinationRule)设置流量捕获和回放的规则。
- 执行回放:根据配置的规则,Service Mesh将捕获的流量转发到测试环境,并进行相应的处理。
应用方式: 基于Service Mesh的流量回放技术适用于微服务架构中的复杂场景,能够灵活地模拟和验证服务间的交互行为,同时保持业务代码的干净和不变。
这些工具和框架各有千秋,选择哪种方案取决于具体的业务需求、技术栈和测试目标。
待深入调研
优势与挑战
优势:
- 降低风险:通过记录线上流量并在开发或测试环境回放,降低代码变动对整体系统带来的风险。
- 提高效率:模拟真实环境进行测试,快速发现潜在问题,提高测试效率。
- 增强可靠性:确保系统在不同负载和情况下的稳定性和可靠性。
挑战:
- 流量复杂性:实际生产环境中的流量复杂多变,处理难度较大。
- 资源占用:流量回放需要占用一定的系统资源,可能影响生产环境的正常运行。
- 技术门槛:流量回放技术需要一定的专业知识和技能支持,对测试人员要求较高。
工具与平台
目前市面上存在多种流量回放工具和平台,如goReplay、tcpCopy、tcpReplay等基于网络协议栈录制的工具,以及众安科技自主研发的众安效能平台等集成化研发工具。这些工具和平台提供了丰富的功能,如流量录制、回放、过滤、断言等,帮助测试人员更好地进行流量回放测试。
未来展望
随着技术的不断发展,流量回放技术将越来越成熟和完善。未来,我们可以期待更多先进的工具和平台出现,为测试人员提供更加便捷、高效的测试方案。同时,随着数字化转型的深入推进,流量回放技术将在更多领域得到应用和推广,为企业的数字化转型提供有力支持。