为什么需要流量复制
对于一些有并发要求的业务,特别是对接外部流量时,产品上线前一定要做的就是压力测试,但是常规的压力测试并不能覆盖所有情况。以gemeter、ab,、webbench、http_load为例,这些通过模拟请求的压测工具,只能发送特定的参数,对于一些参数异常导致的程序处理异常是无法考虑到的,所以就需要一款能复制真实流量,并且不影响线上业务的工具。
流量复制工具有很多,例如Gor、tcpreplay、tcpcopy等,这些工具贴合真实场景,能模拟真实流量,并支持流量的放大或缩小,更容易测试出程序的瓶颈和潜在问题。
常见的流量复制工具有如下几种:
- ngx_http_mirror_module
- tcpcopy
- gor
ngx_http_mirror_module
nginx在1.13.4版本中开始默认加入ngx_http_mirror_module模块,利用mirror模块,业务可以将线上实时访问流量拷贝至其他环境,基于这些流量可以做版本发布前的预先验证,进行流量放大后的压测等等
mirror模块配置分为两部分,源地址和镜像地址配置,示例配置如下
# original配置
location / {
mirror /mirror;
proxy_pass http://127.0.0.1:9502;
}
# mirror配置
location /mirror {
internal; #指定此 location 只能被“内部的”请求调用
proxy_pass http://127.0.0.1:8081 $request_uri;
}
如果将流量复制到故障后端,如果镜像后端出现了故障并不会影响源后端的响应,Nginx忽略了镜像请求的响应。
如果将流量复制到响应缓慢的后端,由于复制的镜像请求和原始请求是相关联的,只要镜像请求没有处理完成,原始请求就会被阻塞。所以如果镜像请求响应很缓慢,原始请求就会被阻塞变慢。
tcpcopy
tcpcopy是一种请求复制(所有基于tcp的packets)工具,可以把在线流量导入到测试系统中去,从而模拟真实运行环境,以便排查测试系统的性能问题和风险。
在tcpcopy 1.0版本中对整个架构进行了改进,将原本低版本tcpcopy需要运行在测试机上的intercept移除放到一个独立的辅助机上来,使得测试机需要做的操作少到仅仅是添加一条路由而已,对整个测试机的性能损耗可以忽略,排除了intercept运行在测试机上时产生的性能影响,使得测试数据更加接近真实水平。
下载和安装tcpcopy和intercept
#tcpcopy
git clone http://github.com/session-replay-tools/TCPCopy
./configure
make
make install
#intercept
git clone http://github.com/session-replay-tools/intercept
./configure
make
make install
tcpcopy和intercept使用示例
#线上服务器,装有tcpcopy,实现流量复制
#将80端口收到的流量复制到测试机ip 172.16.1.25的80端口,并设置辅助机的ip地址为172.16.1.24
tcpcopy -x 80-172.16.1.25:80 -s 172.16.1.24
#辅助服务器,装有intercept,制定捕获规则
#捕获tcp连接中源端口为80的所有数据,也即是测试机的回应数据。其作用是将测试机路由过来的响应数据捕获下来,完成整个请求回应的流程且保证测试机产生的回应数据不会流向线上环境。
intercept -i eth0 -F 'tcp and src port 80'
gor
Gor是用Golang写的一个HTTP实时流量复制工具。只需要在LB或者Varnish入口服务器上执行一个进程,就可以把生产环境的流量复制到任何地方,比如Staging 环境、Dev环境。完美解决了HTTP层实时流量复制和压力测试的问题。
Gor支持流量的放大和缩小、频率限制,这样不需要搭建和生产环境一致的服务器集群也可以正确测试。
Gor还支持根据正则表达式过滤流量,这意味着可以单独测试某个API服务。还可以修改HTTP请求头,比如替换User-Agent, 或者增加某些HTTPHeader。
下载和安装gor
wget https://github.com/buger/gor/releases/download/v0.12.1/gor_0.12.1_x64.tar.gz
tar xzvf gor_0.12.1_x64.tar.gz
cp gor /usr/local/bin
gor使用示例
#简单的HTTP流量复制
gor --input-raw :80 --output-http "127.0.0.1:28020"
#HTTP流量复制频率控制(获取每秒超过10个请求)
gor --input-tcp :28020 --output-http "127.0.0.1:28020|10"
#HTTP流量复制缩小(获取每秒10%请求)
gor --input-raw :80 --output-http "127.0.0.1:28020|10%"
#HTTP流量回放和压测
gor --input-file "requests.gor|200%" --output-http "127.0.0.1:28020"
参考文章
- https://segmentfault.com/a/1190000015936959
- https://www.yangcs.net/posts/nginx-mirror/
- https://www.centos.bz/2017/08/nginx-request-copy-ngx_http_mirror_module/
- https://www.jianshu.com/p/8df317dbf653
- https://winway.github.io/2017/10/17/tcpcopy-introduce/
- https://www.cnblogs.com/zhengyun_ustc/p/tcpcopy.html
- https://www.hi-linux.com/posts/41063.html
- https://www.jianshu.com/p/57e058ad4995