HTTP 流量拷贝测试神器 GoReplay

以下文章来源于 一个 程序员 的 修炼之路 ,作者 河边 一枝 柳

一般在软件发布之前,都会经过单元测试, 接口测试, 集成测试, 性能测试等。但是这些测试往往都是基于自己定义的测试数据集合,很可能会有漏网之鱼,那么在软件上线之后,在线上流量冲击下,会出现各种之前测试中并没有发现的问题。这是因为线上的流量数据比测试的数据更加多样性,并且随着用户数量的增加,线上流量的也越来越大,更多的隐藏问题也会暴露,比如并发处理不当导致的Crash。那么我们有什么方法能够在上线之前完成这些测试呢?有的,那就是GoReplay

GoReplay概述

当前越来越多的产品SaaS化,而SaaS化之后很多的服务都切分成多个微服务,HTTP又是服务之间常用的远程调用方式。
GoReplay是一个用Golang编写的开源的流量复制工具, 基于libpcap(windows也叫做WinpcapNpcap也可以支持),其原理和WiresharkTcpdump类似,是一种非侵入软件方式的流量复制方式。

图源于GoReplay 官方 Wiki

上图是一个典型的应用场景:

  1. GoReplay实现为一个可执行程序,方便运行, 支持WindowsLinux。先将其运行在一个具有流量环境的机器上, 监听指定端口的流量。
  2. GoReplay将监听到的流量,以HTTP发送到指定的一个或者多台测试机器。
  3. 测试人员可以在测试机器上对流量处理结果进行分析。

软件还提供了丰富的功能:

  1. 比如根据HTTP请求的Method, 请求路径, 请求头进行过滤
  2. 可以对请求进行进行改写,比如增加HTTP Header
  3. 可以基于Middleware,可以理解为自己编写插件。在插件中自己可以获取原始请求, 原始响应结果, 以及测试机器返回测试响应结果,这样就可以实现当前机器上的原始响应结果测试响应结果做对比测试。

GoReplay作者提供了编译好的版本,提供下载地址:

https://github.com/buger/goreplay/releases

本文将介绍 如下几个方面,来阐述GoReplay的常见功能,而关于进阶的GoReplay插件实现将放在后续的文章中。

  • 流量复制测试
  • 流量保存到文件和重放功能介绍
  • HTTP请求过滤
  • HTTP请求更改

流量复制测试

现在假设有一台有流量的机器,运行了一个服务,监听端口9797, 客户端使用HTTP和服务通信。

如果你想练练手,可是没有现成服务进程,不要担心,GoReplay本身提供了模拟服务的功能。那么你可以在服务机器上模拟运行sudo ./gor file-server :9797。这个时候你通过浏览器访问这个机器就可以产生流量了。

现在要开始进行测试了,先准备一台测试机器,也运行这个服务。然后进行流量拷贝操作。如下图所示在机器上运行GoReplay命令如下:

sudo ./gor  --input-raw :9797 --output-http "http://<测试机器IP>:9797"

这个时候将会在服务机器上将端口9797上的HTTP流量复制到测试机器

这样做了,你就可以在不影响运行的服务机器,在测试机器上任意的开启调试选项或者更改服务进程的代码等,来辅助进行流量测试分析。是不是没有想到,GoReplay的使用如此简单。

!!!注意!!!: 从实践角度而言,不建议进行在线的流量复制测试,因为只要在线上操作,那就有可能会对线上产生影响。比如服务机器和测试机器在互通的网络之中,如果服务进程可能对第三方比如DB,Redis进行写操作,而测试机器上的服务进程收到同样的流量后,也会进行同样的操作,这样必然容易引起问题。你可以通过修改代码,在测试服务机器上屏蔽对数据库等第三方服务的写操作。但是是人就会犯错误,那有可能屏蔽的不够完全,对线上产生第三方服务的更改产生了影响。所以本人不建议在线上使用这个方法。

那么可以在保证流量落盘符合隐私保护法律和公司操作规范的情况下将流量Dump到本地磁盘文件,然后再在和线上环境隔离的测试环境中进行流量重放的测试和分析。

流量保存到文件和重放功能介绍

若要将流量保存到本地磁盘文件,那就一定要注意自己的行为是不侵犯隐私保护法律的,并且符合公司的规范。下面我们来讲一讲方法:
将流量保存到文件:
sudo ./gor --input-raw :9797 --output-file Traffic.gor
那么将会产生若干个Traffic_*.gor的文件。

如果重放则可以采用如下方式 (支持通配符方式)。

sudo ./gor --input-file  Traffic_*.gor --output-http "http://[测试机器A的IP]:9797" --output-http "http://[测试机器B的IP]:9797"

注意这里特意将流量发送到两台机器了,假设这里的测试机器A采用的是上一个发布版本的软件,而测试机器B采用的是正准备发布的新版本,通过两者运行的结果,比如Log,机器CPU,Memory等情况对比来做对比分析。当然了如果不需要做对比,你也可以只讲流量导入到一个测试机器。

GoReplay重放的时候还可以用来做性能测试分析, 其可以通过放大速率来提高单位时间请求数量,比如下面按照五倍500%速率发送。

sudo ./gor --input-file  "Traffic_*.gor|500%" --output-http "http://[测试机器的IP]:9797"

还可以使用--input-file-loop来实现循环不断的发送:

sudo ./gor --input-file  "Traffic_*.gor|500%" --input-file-loop --output-http "http://[测试机器的IP]:9797"

另外可以使用--stats --output-http-stats来查看一些统计信息,不过本人觉得当前的统计信息还不够清晰。

HTTP请求过滤

HTTP请求的抓取,可以进行一些过滤,从而只抓取和自己感兴趣的请求。
比如下面的命令,只有符合下述条件的才会抓取

  1. --http-allow-url采用正则表达式,只抓取请求URL中含有test的请求;
  2. --http-allow-header采用正则表达式,只抓取XHeader123的请求;
  3. --http-allow-method GET, 只抓取HTTP请求方法为GET的请求。
sudo ./gor --input-raw :9797 --output-file test.gor --http-allow-url .*test.* --http-allow-header XHeader:123 --http-allow-method GET

也可以使用--http-disallow-url--http-disallow-header去除一些不需要抓取的请求,同样支持正则表达式。

HTTP请求更改

有时候你也需要更改HTTP请求,比如你想增加某个HTTP Header去让测试服务器识别,这个Request来自于GoReplay。我们举出一下例子来进行说明:

  1. --http-rewrite-url "/v1/user/([^\\/]+)/ping:/v2/user/$1/ping" 这个采用的是官方文档的案例,表示将/v1/user/([^\\/]+)/ping替换为/v2/user/$1/ping。不过经过本人测试1.3.3的版本替换$1有问题。
  2. --http-set-param "isTest=1" 设置参数isTest1, 如果没有则增加这个参数,如果已经有,则修改这个参数。
  3. --http-set-header "User-Agent: tester agent" 修改或者增加一个HTTP Header
  4. --http-rewrite-header "Host: (.*):9797,$1:9898" 比如原先的HTTP Header为Host: xxx:9797 修改后变成Host: xxx:9898
sudo ./gor --input-raw :9797 --output-file test.gor --http-rewrite-url "/v1/user/([^\\/]+)/ping:/v2/user/$1/ping" --http-set-param "isTest=1" --http-set-header "XGoReplay: 1" --http-set-header "User-Agent: tester agent" --http-rewrite-header "Host: (.*):9797,$1:9898"

这些都是通过GoReplay的命令行参数去进行一些基本的更改HTTP请求的方法。需要更强的重写功能,那必须借助GoReplayMiddlware,支持使用者编写插件去处理,除此之外插件功能也可以根据原始流量的响应结果测试响应结果来实现的结果对比。

总结

GoReplay可以协助我们利用已有的流量进行部分的功能测试,稳定性测试,以及性能测试等等。但是在使用的过程中,一定要注意不要对线上的数据造成影响,并且操作不要侵犯隐私保护法律,遵循公司的操作规范。
对于GoReplay的进阶部分Middleware去编写自己的插件,实现Rewrite和直接的测试结果对比功能,将在后续文章进行阐述。

参考

GoRepay Wiki:

https://github.com/buger/goreplay/wiki

- EOF -

猜你喜欢

转载自blog.csdn.net/osfront/article/details/123475415