参考:https://www.cnblogs.com/zhengyun_ustc/p/tcpcopy.html 真刀真枪压测:基于TCPCopy的仿真压测方案
一、为什么要做仿真测试
线下的传统压力测试,难以模拟真实流量,尤其难以模拟正常流量混杂着各色异常流量。所以,线下压得好好的系统,上线后可能某天突然雪崩,说好能支撑 5 倍流量的系统重构,也许流量一翻倍就彻底挂了。
但办法总比问题多。
(1)系统重构或重要变更上线前,可以拷贝线上真实流量,实时模拟线上流量,甚至可以放大真实流量,进行压力测试,以评估系统承载能力。
(2)反过来也可以这样,如果线上跑着跑着发现有性能瓶颈,但线下环境难以复现,还不如把真实流量拷贝到线下重放,毕竟线下环境便于上各种排查手段,重放几遍都行,直到找到问题
二、如何实时拷贝线上真实流量呢?
TCPCopy。TCPCopy 是一种请求复制(复制基于 TCP 的 packets)工具 ,通过复制在线数据包,修改 TCP/IP 头部信息,发送给测试服务器,达到欺骗测试服务器的TCP 程序的目的,从而为欺骗上层应用打下坚实基础
三、TCPCopy是如何工作的
Tcpcopy需要intercept的支持,tcpcopy负责抓包和发包工作,而intercept负责截获应答包
它的数据流转和部署架构如下图
TCPCopy是用来做TCP重放的,常用的场景是把线上流量复制到测试环境,用来排查线下不容易重现的问题,或者对测试环境做压力测试。
王斌讲过,基于 Server 的请求回放领域,一般分为离线回放和在线实时复制两种。
其中请求实时复制,一般可以分为两类:
1)基于应用层的请求复制 ,
2)基于底层数据包的请求复制。
如果从应用层面进行复制,比如基于服务器的请求复制,实现起来相对简单,但也存在着若干缺点:
1)请求复制从应用层出发,穿透整个协议栈,这样就容易挤占应用的资源,比如宝贵的连接资源 ,
2)测试跟实际应用耦合在一起,容易影响在线系统,
3)也因此很难支撑压力大的请求复制,
4)很难控制网络延迟。
而基于底层数据包的请求复制,可以做到无需穿透整个协议栈,路程最短的,可以从数据链路层抓请求包,从数据链路层发包,路程一般的,可以在IP层抓请求包,从IP层发出去,不管怎么走,只要不走TCP,对在线的影响就会小得多。这也就是 TCPCopy 的基本思路。
四、框架
如Figure1中所示,tcpcopy包括两部分:tcpcopy(client)和intercept(server)(后文中统一将tcpcopy-client称为tcpcopy,将tcpcopy-server称为intercept),当tcpcopy运行在生产服务器并从生产服务器抓取请求时,inteceptor运行在辅助服务器上进行一些辅助工作,例如,响应tcpcopy。切记,测试应用程序应该运行在测试服务器上。
(TCPCopy使用方法:
TCPCopy分为TCPCopy client(即tcpcopy)和TCPCopy server(即intercept)两部分。
其中TCPCopy client运行在在线服务器上面,用来捕获在线请求数据包;
TCPCopy server(默认监听端口为36524)运行在测试机器上面,用来截获响应包,并传递响应包头信息给TCPCopy client,以完成TCP交互。)
tcpcopy默认情况下使用socket输入技术在网络层抓取线上的数据包,做一些基本处理(包括:模拟TCP交互,网络控制,以及模拟传输层和应用层),使用socket输出技术发送数据包到测试服务器(如粉色箭头所示)
tcpcopy的测试服务器需要做的唯一操作是:设置适当的参数使响应信息发送到辅助服务器中(装intercept的服务器)(如绿色箭头所示)
intercept(默认)将响应信息传送给tcpcopy。通过抓取响应包,intercept提取响应头信息,并使用一个特殊的通道将响应头信息发送给tcpcopy(如紫色箭头所示)。当tcpcopy接受到响应头信息,它利用头信息修改在线打包器的属性并继续发送另一个包。应当注意,来自测试服务器的响应被路由到应该充当黑洞的辅助服务器。
对本次压测来说,20那台就是测试服务器(ts),21那台就是辅助服务器(as)
角色 | 主机名 | mysql端口 |
online server | test00 | 3308(5.6) |
assistant server | offline01 | |
target server | offline02 | 3318(5.7) |
安装依赖
# yum -y install libpcap-devel
intercept安装
# git clone git://github.com/session-replay-tools/intercept.git# cd intercept# ./configure# make && make install
tcpcopy安装
# git clone git://github.com/session-replay-tools/tcpcopy.git# cd tcpcopy# ./configure# make && make install
# route add -net 10.0.0.8 netmask 255.255.252.0 gw 10.0.0.0
成功后可以看到
# ss -an |headState Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 0 127.0.0.1:199 *:*
LISTEN 512 0 *:80 *:*
ESTAB 0 0 192.168.0.230:80 10.10.10.1:62602ESTAB 0 0 192.168.0.230:80 10.10.10.4:54595ESTAB 0 0 192.168.0.230:80 10.10.10.3:53566ESTAB 0 0 192.168.0.230:80 10.10.10.6:49260ESTAB 0 0 192.168.0.230:80 10.10.10.8:57598ESTAB 0 0 192.168.0.230:80 10.10.10.7:64454
# cd /usr/local/intercept/sbin/
# ./intercept -i bond1 -F 'tcp and src port 3318' -d
成功后可以看到
# ss -an |grep 36524LISTEN 0 5 *:36524 *:*
ESTAB 0 66 192.168.0.219:36524 192.168.0.8:49034 ESTAB 0 0 192.168.0.219:36524 192.168.0.8:49035 ESTAB 0 66 192.168.0.219:36524 192.168.0.8:49032 ESTAB 0 0 192.168.0.219:36524 192.168.0.8:49033
# cd /usr/local/tcpcopy/sbin/# ./tcpcopy -x 3308-10.0.0.1:3318 -s 10.0.0.2 -c 10.0.0.8 -d
成功后可以看到
#ss -an|grep 192.168.0.219ESTAB 0 0 192.168.0.8:49034 192.168.0.219:36524 ESTAB 0 0 192.168.0.8:49035 192.168.0.219:36524 ESTAB 0 0 192.168.0.8:49032 192.168.0.219:36524 ESTAB 0 0 192.168.0.8:49033 192.168.0.219:36524
1、tcpcopy log日志提示many connections cant established
把tcpcopy指定的-c 伪装客户端ip换成和线上一致的,可以ping通的网段就可以
2、大多数云环境设置了安全限制,一个网卡无法绑定2个IP,所以online server则会拒绝发送复制包,在线上抓包就会显示
# tcpdump -i eth0 -nn port 3306 and host 1.1.1.411:53:58.573735 IP 10.0.0.1.https > 10.0.0.2.37121: Flags [R.], seq 0, ack 2906947315, win 0, length 0
11:53:58.573774 IP 10.0.0.2.37121 > 10.0.0.1.http: Flags [.], ack 2906947314, win 1024, length 0
11:53:58.573812 IP 10.0.0.1.http > 10.0.0.2.37121: Flags [R], seq 2906947314, win 0, length 0
tcpcopy拷贝一次流量访问的步骤如下:
1、一个访问请求到达线上内核后端机;2、socket 包在 IP 层被拷贝了一份传给tcpcopy 进程;3、tcpcopy 修改包的目的及源地址,发给测试内核后端机;4、拷贝的包到达测试内核后端机;5、测试内核后端机的推荐内核处理访问,并返回结果;6、返回结果在 IP 层被截获、丢弃,由 intercept 拷贝返回结果的 IP header 返回;7、IP header 被发送给线上内核后端机的 tcpcopy 进程。