目录

HTTP流量拷贝测试神器GoReplay

HTTP流量拷贝测试神器GoReplay

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

GoReplay概述

当前越来越多的产品SaaS化,而SaaS化之后很多的服务都切分成多个 微服务 ,HTTP又是服务之间常用的远程调用方式。

GoReplay 是一个用 Golang 编写的开源的流量复制工具, 基于 libpcap (windows也叫做 WinpcapNpcap 也可以支持),其原理和 WiresharkTcpdump 类似,是一种非侵入软件方式的流量复制方式。( 下图来自于GoReplay 官方 Wiki

https://i-blog.csdnimg.cn/blog_migrate/99b54b0f5424d4a7d27c2c2e02d5608a.png

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

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

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

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

GoReplay 作者提供了编译好的版本,提供 。

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

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

流量复制测试

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

https://i-blog.csdnimg.cn/blog_migrate/d84b4da92784050da74bfb0f8d24a573.png

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

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

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

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

https://i-blog.csdnimg.cn/blog_migrate/ddfb249596ae892bc13e1a0f2dcd3753.png

这样做了,你就可以在不影响运行的 服务机器 ,在 测试机器 上任意的开启调试选项或者更改 服务进程 的代码等,来辅助进行流量测试分析。是不是没有想到, 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"

https://i-blog.csdnimg.cn/blog_migrate/ea872b897fc54890f5205dea3a605733.png

注意这里特意将流量发送到两台机器了,假设这里的 测试机器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和直接的测试结果对比功能,将在后续文章进行阐述。

参考