天天看点

TCPcopy:分布式TCP压力测试工具

线下的传统压力测试,难以模拟真实流量,尤其难以模拟正常流量混杂着各色异常流量。所以,线下压得好好的系统,上线后可能某天突然雪崩,说好能支撑 5 倍流量的系统重构,也许流量一翻倍就彻底挂了。

但办法总比问题多。

系统重构或重要变更上线前,可以拷贝线上真实流量,实时模拟线上流量,甚至可以放大真实流量,进行压力测试,以评估系统承载能力。

反过来也可以这样,如果线上跑着跑着发现有性能瓶颈,但线下环境难以复现,还不如把真实流量拷贝到线下重放,毕竟线下环境便于上各种排查手段,重放几遍都行,直到找到问题。

如何实时拷贝线上真实流量呢?TCPCopy

2010年,网易技术部的王斌在王波的工作基础上开发了 TCPCopy - A TCP Stream Replay Tool。2011年9月开源。当前版本号是 1.0.0。很多公司的模拟在线测试都是基于 TCPCopy 做的,如一淘。

TCPCopy 是一种请求复制(复制基于 TCP 的 packets)工具 ,通过复制在线数据包,修改 TCP/IP 头部信息,发送给测试服务器,达到欺骗测试服务器的TCP 程序的目的,从而为欺骗上层应用打下坚实基础。

TCPCopy是如何工作的

基于 Server 的请求回放领域,一般分为离线回放和在线实时复制两种。

其中请求实时复制,一般可以分为两类:

1)基于应用层的请求复制 ,

2)基于底层数据包的请求复制。

如果从应用层面进行复制,比如基于服务器的请求复制,实现起来相对简单,但也存在着若干缺点:

1)请求复制从应用层出发,穿透整个协议栈,这样就容易挤占应用的资源,比如宝贵的连接资源 

2)测试跟实际应用耦合在一起,容易影响在线系统,

3)也因此很难支撑压力大的请求复制,

4)很难控制网络延迟。

而基于底层数据包的请求复制,可以做到无需穿透整个协议栈,路程最短的,可以从数据链路层抓请求包,从数据链路层发包,路程一般的,可以在IP层抓请求包,从IP层发出去,不管怎么走,只要不走TCP,对在线的影响就会小得多。这也就是 TCPCopy 的基本思路。

从传统架构的 rawsocket+iptable+netlink,到新架构的 pacp+route,它经历了三次架构调整,现如今的 TCPCopy 分为三个角色:

Online Server(OS):上面要部署 TCPCopy,从数据链路层(pcap 接口)抓请求数据包,发包是从IP层发出去;

Test Server(TS):最新的架构调整把 intercept 的工作从 TS 中 offload 出来。TS 设置路由信息,把 被测应用 的需要被捕获的响应数据包信息路由到 AS;

Assistant Server(AS):这是一台独立的辅助服务器,原则上一定要用同网段的一台闲置服务器来充当辅助服务器。AS 在数据链路层截获到响应包,从中抽取出有用的信息,再返回给相应的 OS 上的 tcpcopy 进程。

tcpcopy项目地址:https://github.com/session-replay-tools/tcpcopy

Online Server 上的抓包:

tcpcopy 的新架构在 OS 上抓请求数据包默认采用 raw socket input 接口抓包。王斌则推荐采用 pcap 抓包,安装命令如下:

yum install libpcap-devel

git clone git://github.com/session-replay-tools/tcpcopy.git

cd tcpcopy

./configure

make

make install

这样就可以在内核态进行过滤,否则只能在用户态进行包的过滤,而且在 intercept 端或者 tcpcopy 端设置 filter(通过 -F 参数,类似 tcpdump 的 filter),达到起多个实例来共同完成抓包的工作,这样可扩展性就更强,适合于超级高并发的场合。

为了便于理解 pcap 抓包,下面简单描述一下 libpcap 的工作原理。

一个包的捕捉分为三个主要部分:

面向底层包捕获,

面向中间层的数据包过滤,

面向应用层的用户接口。

这与 Linux 操作系统对数据包的处理流程是相同的(网卡->网卡驱动->数据链路层->IP层->传输层->应用程序)。包捕获机制是在数据链路层增加一个旁路处理(并不干扰系统自身的网络协议栈的处理),对发送和接收的数据包通过Linux内核做过滤和缓冲处理,最后直接传递给上层应用程序。如下图2所示:

Online Server 上的发包:

如图1所示,新架构和传统架构一样,OS 默认使用 raw socket output 接口发包,此时发包命令如下:

./tcpcopy -x 80-测试机IP:测试机应用端口 -s 服务器IP -i eth0

其中 -i 参数指定 pcap 从哪个网卡抓取请求包。

此外,新架构还支持通过 pcap_inject(编译时候增加--enable-dlinject)来发包。

Test Server 上的响应包路由:

需要在 Test Server 上添加静态路由,确保被测试应用程序的响应包路由到辅助测试服务器,而不是回包给 Online Server。

Assistant Server 上的捕获响应包:

辅助服务器要确保没有开启路由模式 cat /proc/sys/net/ipv4/ip_forward,为0表示没有开启。

辅助服务器上的 intercept 进程通过 pcap 抓取测试机应用程序的响应包,将头部抽取后发送给 Online Server 上的 tcpcopy 进程,从而完成一次请求的复制。

实验

1.机器别表

192.168.0.11 -- onlie server

192.168.0.12 -- test server

192.168.0.13 -- Assistant server

2.online server操作

安装tcpcopy

启动TCPCOPY

./sbin/tcpcopy -x 80-192.168.0.12:80 -s 192.168.0.13 -c 192.168.0.11

-x 参数指定本机哪个端口的流量转发到哪台机器的哪个端口,格式为localip:80-targetip:port

-s 参数指定Assistant server -c 指定本机

可以添加-n参数来放大流量,比如说 -n 2 代表放大2倍流量

可以添加-r参数来复制一部分流量。比如说,-r 20 代表复制20%的流量

可以添加-d参数来让tcpcopy后台运行

3.test server操作

route add host 192.168.0.11 gw 192.168.0.13

这一步很重要,之前我就是因为这个路由设置不正确,一直没搭建成功

4.Assistant server操作

安装intercept

git clone git://github.com/session-replay-tools/intercept.git

cd intercept

启动intercept

./sbin/intercept -i eth0 -F tcp and src port 80 -d

-i 指定网卡

-F 指定copy的是tcp还是udp

-d 代表后台运行

我这里默认online server还有test server都启动了nginx。当你访问online server上的http服务的时候。你会发现test server上也有访问log存在。可以通过监控test server上的负载,来判断机器的运行情况