主题
全链路压测
方式一: tcpcopy 录制线上的流量请求, 进行流量放大
简介
TCPCopy是一个TCP流重放工具,用于对互联网服务器应用进行实际测试。
尽管实际的实时流量对于测试互联网服务器应用至关重要,但由于在线环境的复杂性,准确模拟它是一个挑战。为了实现更真实的测试,TCPCopy作为一个实时流量复制工具被开发出来,它生成的测试工作负载与生产工作负载非常相似。TCPCopy在中国的公司中被广泛使用。
TCPCopy对生产系统的影响很小,只消耗额外的CPU、内存和带宽。复制的工作负载在请求多样性、网络延迟和资源使用方面都反映了生产环境。
架构
TCPCopy由两个组件组成:tcpcopy
和intercept
。tcpcopy
组件在在线服务器上运行,捕获实时请求,而intercept
在辅助服务器上运行,执行将响应信息传递给tcpcopy
等任务。测试应用程序本身在目标服务器上运行。
默认情况下,tcpcopy
使用原始套接字在网络层捕获数据包(图中以橙色箭头表示)。它处理TCP交互模拟、网络延迟控制和上层交互模拟等过程。然后,它使用原始套接字将数据包发送到目标服务器进行输出(图中以浅红色箭头表示)。
目标服务器上唯一需要的任务是配置路由规则,将响应数据包(图中以浅绿色箭头表示)定向到辅助服务器。
intercept
组件的作用是将响应头(默认)转发给tcpcopy
。它捕获响应数据包,提取响应头信息,并通过专用通道将此信息发送给tcpcopy
(图中以浅蓝色箭头表示)。在接收到响应头后,tcpcopy
使用这些信息修改在线数据包的属性,并继续发送后续数据包。
需要注意的是,来自目标服务器的响应被路由到辅助服务器,辅助服务器充当黑洞。
实战
配置环境
TCPCopy --> TCPCopy V1.0.0
线上服务器 --> 192.168.124.105
测试服务器 --> 192.168.124.68
辅助服务器 --> 192.168.124.180
在我的这个配置环境有三台服务器,一台模拟线上服务器,一台作为测试服务器,还有一台作为辅助服务器。流程如下:
- tcpcopy运行在线上服务器上,tcpcopy会把线上服务器收到的流量,重放给测试服务器,重放的时候tcpcopy修改了IP数据包的源IP地址(譬如修改源地址为192.168.2.254)。所以,线上服务器和测试服务器应该部署相同的服务。
- tcpcopy把源IP伪造成192.168.2.254的包发给了测试服务器,如此,测试服务器在处理完tcpcopy发过来的数据以后,会把这些数据包返回给客户端,即伪造的192.168.2.254。
- 由于没有192.168.2.254这个地址,我们在测试服务器添加一条专门的路由,把发往192.168.2.0/24的数据包,都全部转交给辅助服务器。
- 为了保证辅助服务器会接受这些本不属于自己的,部署在辅助服务器上的intercept就发挥作用了。辅助服务器还可以用来把客户端的请求返回给tcpcopy,但是默认只返回响应头部给tcpcopy。辅助服务器应该类似于黑洞。
线上机器安装tcpcopy
在线上服务器上下载,然后编译安装tcpcopy的包,如下:
sh
wget https://github.com/session-replay-tools/tcpcopy/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd tcpcopy-1.0.0
./configure --prefix=/opt/tcpcopy/
make
make install
辅助机器安装intercept
安装intercept有一些额外的依赖需要安装上,然后和tcpcopy一样的套路源码编译安装。
sh
yum -y install libpcap-devel
https://github.com/session-replay-tools/intercept/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd intercept-1.0.0
./configure --prefix=/opt/tcpcopy/
make
make install
部署
先在辅助服务器上开启intercept,步骤不能错,没有intercept的话,tcpcopy启动不起来:
sh
/opt/tcpcopy/sbin/intercept -i eth0 -F 'tcp and src port 8000' -d
- -i, intercept会监听端口,和tcpcopy进行通信,-i就是指定监听在哪个端口。tcpcopy启动的时候会来连这个端口,如果连不上,就会启动失败。
- -F, 过滤规则,语法和pcap一样。
- -d, 已守护进程方式运行
还有其它参数可以使用,-h便可以查看,不详细解释了。
然后,在线上服务器开启tcpcopy:
sh
/opt/tcpcopy/sbin/tcpcopy -x 8000-192.168.124.68:8000 -s 192.168.124.180 -c 192.168.2.254 -n 2 -d
- -x, 是指本机8000端口的流量copy到192.168.124.68的8000端口
- -s, 指定intercept机器的地址,tcpcopy要和intercept建立连接
- -c 伪装地址,在把流量复制到测试服务器的时候,修改数据包的源地址为192.168.2.254,这样方便指定路由。也可以写成192.168.2.x,这样源地址就是指定网段中的地址了。
- -n 流量放大倍数,如果不是压测目的就不用指定这个参数。
- -d 以守护模式运行。
最后,在测试服务器上开启路由(切记辅助服务器要和测试服务器在一个子网里):
sh
route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.124.180
路由的意思是把发往192.168.2.0/24地址的数据包全部转给辅助服务器。
附: ssl协议处理方法
nginx
server {
listen 443 ssl;
server_name xxx.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:8000; # 明文后端服务
}
}
nginx配置这样就可以通过 TCPCopy 转发解密后的 HTTP 流量
注意事项
- 仅在Linux(内核2.6或以上)上测试过。
- 可能丢失数据包。 (尽可能所有机器在同一内网中)
- 需要root权限或CAP_NET_RAW能力。
- 目前仅支持客户端发起的连接。
- 不支持SSL/TLS应用的重放。 (但可以监听nginx解析https后重定向的http请求地址, 也就是指向后端业务服务的请求)
- 由于tcpcopy增加了转发层,单个应用连接的吞吐量不能太高。
- 如果复制的请求量过大,tcpcopy可能会变得不稳定。
- MySQL会话重放的详细信息。
- intercept和tcpcopy的某些配置选项不能一起使用。
- 确保辅助服务器上没有启用ip_forward。