关于作者
前滴滴出行技术专家,现任OPPO文档数据库mongodb负责人,负责oppo千万级峰值TPS/十万亿级数据量文档数据库mongodb内核研发及运维工作,一直专注于分布式缓存、高性能服务端、数据库、中间件等相关研发。后续持续分享《MongoDB内核源码设计、性能优化、最佳运维实践》,Github账号地址:https://github.com/y123456yz
1. 简介
TCPCopy是一种请求复制(所有基于tcp的packets)工具,可以把在线流量导入到测试系统中去。目前此工具已经广泛应用于各大互联网公司。
项目网址:https://github.com/wangbin579/tcpcopy
https://github.com/session-replay-tools/intercept
2. TCPCopy功能
1)分布式压力测试工具,利用在线数据,可以测试系统能够承受的压力大小(远比ab压力测试工具真实地多),也可以提前发现一些bug
2)普通上线测试,可以发现新系统是否稳定,提前发现上线过程中会出现的诸多问题,让开发者有信心上线
3)对比试验,同样请求,针对不同或不同版本程序,可以做性能对比等试验
4)流量放大功能,可以利用多种手段构造无限在线压力,满足中小网站压力测试要求
5)利用TCPCopy转发传统压力测试工具发出的请求,可以增加网络延迟,使其压力测试更加真实
6)热备份
3.组成部分
1. TCPCopy Server(tcpcopy):部署在 测试服务器 ,用于接收复制的线上请求,github地址:
https://github.com/session-replay-tools/tcpburn
2. TCPCopy Client(intercept):部署在 线上服务器 ,用于捕获线上请求,通过修改TCP/IP数据包,发送到TCPCopy Server进行稳定性测试,截获响应包,并传递响应包头信息给TCPCopy client,以完成TCP交互。Github地址:
https://github.com/session-replay-tools/interceptgithub.com4. tcpcopy工作流程
![6556f84f4226c917b003f68458ab078f.png](https://i-blog.csdnimg.cn/blog_migrate/2b574b83c9b62906439793955ec5eb6e.png)
一个访问到达线上前端机;
socket数据包在ip层被拷贝了一份传给tcpcopy进程;
tcpcopy修改包的目的及源地址,发给目标测试机;
拷贝的包到达目标测试机;
目标测试机的nginx处理访问,并返回结果;
返回结果在ip层被截获、丢弃,由intercpet进程拷贝返回结果的ip header并返回;intercept会通过tcpcopy与intercept之间的套接字来发送tcpcopy重放报文中的IP+TCP数据给tcpcopy,可以参考intercept中的函数tc_socket_snd
ip header被发送给线上前端机的tcpcopy进程。
5. 常见的几种引流方式
5.1 离线流量回放
用法:离线回放模式需要在configure 的时候加上--enable-offline 参数,离线回放还需要安装pcap 库和pcap 开发库(需要用到pcap 库的头文件)另外运行的时候需要指定-i 参数,例如:
./tcpcopy -x 110-xxx.xxx.xxx.148:110 -i ./online.pcap
这里oline.pcap(利用类似于tcpdump 的工具来抓请求数据包,存放到pcap 格式的文件中去)文件作为数据源,把请求转发到测试服务器上。此外增加-a参数对请求数据包的访问进行加速,如下:
./tcpcopy -x 80-xxx.xxx.x.xx:8080 -a 2 -i online.pcap
假设online.pcap 文件为在线请求数据包的抓包文件,时间间隔为60 分钟。执行此命令后,离线回放加速了2 倍,只需要30 分钟离线回放就能完成,-a 参数设置不宜设置过大,越大丢请求的概率也越大。
适用场景:由于离线方式依赖于抓包工具(如tcpdump),而抓包工具在压力比较大的场合一般丢包非常严重,而且还会严重影响在线IO,因此一般不推荐在高压情况下使用离线回放方式
1、tcpcpoy和测试组件合设。
2、一台机器起多个tcpcopy.用虚拟机。先试一下。或者看下代码,确认(所有疑惑点。真正的技术点)。
系统全链路压测系统。慢慢了解下性能测试团队。
5.2 部分引流
用法:Tcpcopy可以通过-r参数实现在线服务器应用的部分流量复制,参数范围是1~99,其它值都是全流量复制。-r 参数常用于测试服务器配置不如在线服务器的场合。
#./tcpcopy -x http://2080-xxx.xx.xx.xxx:9999 -r 20
这里tcpcopy 复制在线服务器2080 端口应用的20%流量给测试服务器,这里的20%是根据session(这里session 是由客户端IP,客户端端口决定)来统计的。
适用场景:部分引流主要适用于线上请求压力很多,而测试环境的处理能力较弱,这时候就只需复制部分线上的请求到测试环境,就可以压到测试环境的极限.
5.3 放大流量
用法:Tcpcopy可以通过-n参数对在线服务器应用的流量进行复制放到到测试服务器,如果你要进行多重复制,-n参数
#./tcpcopy -x http://2080-xxx.xx.x.xxx:9999 -n 3
表示复制3 倍的在线服务器的80 端口应用请求流量到192.168.0.2 的8080 端口
适用场景:放大引流主要用于线上压力较小时,想要通过无限构造压力通过成倍引流达到对测试服务器进行压力测试的目的
6. 应用举例
TCPCopy分为TCPCopy client(也即tcpcopy)和TCPCopy server(也即intercept)。其中TCPCopy client运行在在线服务器上面,用来捕获在线请求数据包;TCPCopy server(默认监听端口为36524)运行在测试机器上面,用来截获响应包,并传递响应包头信息给TCPCopy client,以完成TCP交互。
说明:以下测试环境中真实服务器IP地址172.16.3.66,测试服务器1的ip地址为172.16.3.42,测试服务器2的ip地址为172.16.3.41,其中测试服务器2是运行intercept进程的额外服务器,只是为了配合测试用。
目的:复制172.16.3.66上的11111端口流量到测试服务器172.16.3.42中的11111
首先在测试服务器172.16.3.41上启用Ip_queue内核模块,同时按照以下方式对Iptable进行设置:
- 加载ip_queue内核模块,如果已经有加载nfnetlink_queue模块,则需要先卸载该模块 modprobe ip_queue
- 编辑/etc/sysconfig/iptables,添加:Iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 36524 -j ACCEPT
- 然后重启
iptables:
/etc/init.d/iptables restart - 将响应结果发送至QUEUE(
ip_queue
),从而实现运行在用户态的进程对相关数据包进行裁定,执行以下命令:
iptables -I OUTPUT -p tcp --sport 11111 -j QUEUE
iptables -A INPUT -p --dport http -j QUEUE
这个规则的意思是linux将http服务的报文上送到用户层,而做这个工作的就是ip_queue。ip_queue是一个处理QUEUE动作的一个模块。
6.1 离线回放配置
- 在真实服务器172.16.3.66上面抓包:
tcpdump -i eth0 tcp and host 172.16.3.66 and port 11111 –s 2000 –w online.pcap,
注意这里-s后面不能为0,或者不带-s参数,这两种情况下会造成抓包丢包。-s后面的数字大小最好根据实际包体大小进行调试。丢包调试参数还有:
echo 124928000 > /proc/sys/net/core/rmem_max
echo 1249280 > /proc/sys/net/core/rmem_default
2. 拷贝步骤1的online.pcap到测试服务器1,即1716.3.42
3. 编译tcpcopy,./configure --offline,然后make && make install。如果提示以下错误:
checking for pcap.h ... not found,则需要yum install libpcap-devel
tcpcopy: illegal argument "i",说明是configure的时候没有携带—offline
yum install openssl openssl-devel
4. 在测试服务器2,即172.16.3.41上面运行intercept工具
/usr/local/intercept/sbin/intercept -i eth0 -F 'tcp and src port 11111' &
5. 在测试服务器1,即172.16.3.42上面设置路由,把本来应该应答给192.168.1.x的报文转发给运行intercept的172.16.3.41服务器处理。
Route add –net 192.168.1.0 netmask 255.255.255.0 gw 172.16.3.41
6. 在在线服务器上面执行tcpcopy工具进行流量回放。
在线引流编译tcpcopy的时候直接./configure—offline,无需./configure --offline
把在线服务器中端口地址为11111的报文转发到172.16.3.42:11111测试服务器上,同时修改报文的源Ip地址为192.168.1.x。修改原ip地址的好处是服务器1上面设置应答路由方便。
/usr/local/tcpcopy/sbin/tcpcopy -x 11111-172.16.3.42:11111 -i ./online.pcap -s 172.16.3.41 -c 192.168.1.x &
6.2 在线实时引流
- 在在线服务器172.16.3.66上编译tcpcopy,./configure,然后make && make install。如果提示以下错误:
checking for pcap.h ... not found,则需要yum install libpcap-devel
2. 在测试服务器2,即172.16.3.41上面运行intercept工具
/usr/local/intercept/sbin/intercept -i eth0 -F 'tcp and src port 11111' &
3. 在测试服务器1,即172.16.42上面设置路由,把本来应该应答给192.168.1.x的报文转发给运行intercept的172.16.41服务器处理。
Route add –net 192.168.1.0 netmask 255.255.255.0 gw 172.16.3.41
4. 在在线服务器上面执行tcpcopy工具进行流量回放。
把在线服务器中端口地址为11111的报文转发到172.16.3.42:11111测试服务器上,同时修改报文的源Ip地址为192.168.1.x。修改原ip地址的好处是服务器1上面设置应答路由方便。
/usr/local/tcpcopy/sbin/tcpcopy -x 11111-172.16.3.42:11111 -s 172.16.3.41 -c 192.168.1.x &
7. 测试结果
离线测试
以下测试结果都是以memcached为例:
mc-benchmark -h 172.136.3.66 -p 11111 -c 200 -n 99699999 -d 5 -k 0 -r 565655
![5a45063b6c54a4788006066ccf636331.png](https://i-blog.csdnimg.cn/blog_migrate/f36db4e6e8d4c34559e6e32176c35fd2.jpeg)
8. 注意可能出现的坑
如果目的服务器和部署Intercept的服务器时同一网段,即使启用了intercept进行数据包DROP操作,但是部署intercept的服务器会认为这不是一条最优路由,于是发送icmp重定向报文给目的服务器,这样下次发往该目的服务器的报文会全部直接发往ICMP redirect 192.168.1.1 to host 10.x.4.1, length 60 指定的10.x.4.1地址,这样就会有部分报文走到10.x.4.1这个网关等设备,如果这些网络设备发现到我们模拟的192.168.1.x网段没有路由,就会做snat映射。由于这些网络设备只有一个出口IP,该出口IP可用的端口号最多为65000左右,这时候会造成源地址是192.168.1.x(端口变化)网段的报文消耗掉大量snat的端口,从而造成其他提供服务的内网机器的报文无法转出去。
Icmp重定向相关信息可以参考http://blog.csdn.net/petershina/article/details/41449983
解决办法,可以在Intercept所在垃圾回收器中关闭IP_FOWARD:echo 0 > /proc/sys/net/ipv4/ip_forward