日常大部分的测试工作都是在测试环境下,通过模拟用户的行为来对系统进行验证,但是线下模拟场景有限,会出现业务覆盖不全的情况,通过把线上的真实流量复制到线下环境,解决测试环境模拟不够真实,或覆盖不够全面的问题。通过调研,决定用GoReplay + Diffy开源工具。

GoReplay介绍

GoReplay 主要用于流量录制和回放

工作流程图

Goreplay工作流程图

Diffy工具介绍

Diffy 是一个开源的自动化测试工具,主要基于稳定版本和它的副本的输出,对候选版本的输出进行比较,以检查候选版本是否正确。

工作原理

  1. 通过向稳定版本和稳定版本副本回放流量,对比其流量差异得到噪音
  2. 通过向候选版本和稳定版本回放流量,对比其流量差异得到原始区别
  3. 再从原始区别剔除噪音得到最终的diff结果

Diffy工作流程图

Diffy工作流程图

GoReplay+Diffy工作流程图

GoReplay+Diffy工作流程图

Goreplay使用教程

项目地址:https://github.com/buger/goreplay

安装

二进制文件安装 下载二进制文件

1
2
3
4
5
6
tar -zxvf gor_1.3.3_x64.tar.gz
mv gor /usr/local/bin/
type gor

#root用户执行,让www用户可以使用
setcap "cap_net_raw,cap_net_admin+eip"  gor

编译安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#安装依赖
yum install flex bison -y

wget http://www.tcpdump.org/release/libpcap-1.7.4.tar.gz && tar xzf libpcap-1.7.4.tar.gz
cd libpcap-1.7.4
./configure && make install

#源码编译
git clone https://github.com/buger/goreplay.git
cd  goreplay
go mod tidy
go mod vendor

#需要开启CGO,否则无法编译
CGO_ENABLED=1 go build -o ./bin/gor ./cmd/gor/

参数说明

Gor可用输入

参数 说明 示例
-input-raw 用于捕获HTTP流量,需要指定IP地址或端口 gor –input-raw :8000
-input-raw-track-response 默认关闭,开启后会捕获响应数据, 如果响应数据Content-Type:text/html; charset=UTF-8 并且Content-Encoding: gzip响应数据会乱码,需要加上prettify-http参数 gor –input-raw :8000–input-raw-track-response –prettify-http
-input-file 捕获流量保存的文件 gor –input-file demo.gor
–input-tcp 如果您决定将来自多个转发器Gor实例的流量转发给它,则由Gor聚合实例使用 gor –input-tcp :8000–output-http “http://test1.com” –output-http “http://test2.com
–input-file-loop 实现无限重播

Gor可用输出

参数 说明 示例
–output-http 重放HTTP流量到给定的端点 gor –input-file 20240112.gor –output-http=“http://127.0.0.1:8003”
–output-file 记录传入的流量到文件 gor –input-raw :8000 –output-file %Y%m%d.gor
–output-file-append 记录文件以追加的模式 gor –input-raw :8000 –output-file %Y%m%d.gor –output-file-append
–output-stdout 用于调试,输出所有数据到stdout gor –input-raw  :8000 –output-stdout

请求过滤(gor支持基于url、HTTP头、HTTP方法进行过滤)

参数 说明 示例
–http-allow-url 允许URL正则表达式 gor –input-raw :8000–http-allow-url  ‘/api’
–http-disallow-url 禁止URL正则表达式 gor –input-raw :8000–http-disallow-url  ‘/api’
–http-allow-header 基于HTTP头的正则表达式筛选 gor –input-raw :8000–output-http staging.com –http-allow-header api-version:^1.0\d
–http-allow-method 基于HTTP方法过滤 gor –input-file “20240105.gor”  –http-allow-method POST
–http-allow-host 允许host gor –input-file “20240105.gor”  –http-allow-host  webstore.menaapp.net

请求重写(gor支持重写URL、URL参数、HTTP头)

参数 说明 示例
–http-set-header 设置消息头,如果HTTP头已经存在,它将被覆盖 gor –input-file “20240105.gor”   –http-allow-url ‘/api/store/goods’  –http-set-header ‘Content-Type:application/json’  –output-http=“http://127.0.0.1:8880”
–http-set-param 设置请求url参数,如果参数已经存在,它将被覆盖 gor –input-raw :8000–output-http staging.com –http-set-param api_key=1
–http-rewrite-url 根据映射重写URL gor –input-raw :8000–output-http staging.com –http-rewrite-url /v1/user/([^\/]+)/ping:/v2/user/$1/ping"

演示示例

录制流量

1
2
3
4
5
#监听80端口,会录制该机器上面所有域名请求流量
gor --input-raw :80 --output-file %Y%m%d.gor --output-file-append

#只监听后端端口8080请求流量
gor --input-raw :8080 --output-file %Y%m%d.gor --output-file-append

回放流量

1
2
3
#只允许POST请求,过滤OPTIONS请求,允许URL/api/

gor --input-file "20240112.gor"  --http-allow-method POST  --http-allow-url '/api/'  --output-http="http://127.0.0.1:8000"

其他问题

不能监听443端口数据,可以用以下方式解决

  1. 通过反向代理方式监听后端端口,php项目通过Nginx再转一层;
  2. 线上用的阿里云负载均衡器,只需要监听80端口,就可以监听所有http和https请求

Diffy使用教程

项目地址:https://github.com/opendiffy/diffy

安装部署Diffy

1
2
3
4
#下载Java 17二进制文件
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
yum -y install ./jdk-17_linux-x64_bin.rpm
java -version

参数说明

  1. candidate 重构后新代码的网络地址
  2. master.primary 旧代码的网络地址,用于为正确行为提供基线
  3. master.secondary 用于检测噪音的旧代码的另一个实例的网络地址
  4. proxy.port 此端口用于接收将转发到服务实例的请求
  5. http.port 此端口用于为 UI 提供服务
  6. allowHttpSideEffects 出于安全原因,默认情况下会忽略 POST、PUT、PATCH、DELETE。将参数添加到 –allowHttpSideEffects=true 命令行以启用

启动服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
java -jar ./diffy.jar \
--candidate='127.0.0.1:8003' \
--master.primary='127.0.0.1:8001' \
--master.secondary='127.0.0.1:8002' \
--responseMode='candidate' \
--allowHttpSideEffects='true' \
--service.protocol=http \
--serviceName=My-Service \
--proxy.port=8880 \
--http.port=8888

#监听18000流量
gor --input-raw :8000 --output-http="http://127.0.0.1:8880"

#浏览器查看Diffy UI界面
http://127.0.0.1:8888

Diffy-UI