流量复制技术-tcpcopy
TCPCopy 是一个 TCP 流转发工具,支持互联网服务器应用程序的实际测试
# 一、简介
- 背景:线上流量过于复杂,难以模拟出真实的请求对线上服务进行测试;
- TCPCopy 作为一个实时流重放工具,能够生成类似于生产环境的流量;
- TCPCopy 是对 tcp 包进行转发,与应用层协议无关,mysql、redis、http等都可以转发;
- TCPCopy 除了占用额外的 CPU、内存和带宽外,对生产系统几乎没有影响;
- 复制工作负载在请求多样性、网络延迟和资源占用方面与生产工作负载相似。
# 二、应用场景
- 分布式压力测试:
- 使用 TCPCopy 复制真实数据,对服务器软件进行压力测试,可以找到只能在高压力情况下产生的错误;
- 稳定性测试:
- 证明新系统是稳定的,并找到只发生在生产环境中的错误;
- 回归测试:
- 利用 TCPCopy 复制生产流量,复现bug问题;
- 性能比较:
- 利用 TCPCopy 复制或放大生产流量,验证新版本性能是否达标;
# 三、架构设计
- TCPCOPY 默认使用原始套接字输入技术在网络层捕获在线数据包并进行必要的处理(包括TCP交互模拟、网络延迟控制和常见的上层交互模拟),并默认使用原始套接字输出技术将数据包发送到目标服务器(图中用粉红色箭头表示);
- TCPCopy 由两部分组成:tcpcopy 和 intercept;
- tcpcopy 运行在线上服务器,对真实请求的 tcp 包进行复制并转发到目标服务器上;
- intercept 运行在辅助服务器上,执行一些辅助工作,例如将目标服务器的响应信息传递给 tcpcopy;
- intercept 将提取响应标头信息,并使用特殊通道将响应标头发送到 tcpcopy(图中紫色箭头所示);
- tcpcopy 收到响应标头时,它会利用标头信息修改联机数据包的属性,并继续发送另一个数据包;
- 目标服务器上唯一需要的操作是设置适当的路由命令,以将响应数据包(图中的绿色箭头所示)路由到辅助服务器;
- 应该注意的是,来自目标服务器的响应被路由到辅助服务器,该服务器应该充当黑洞;
# 四、安装与说明
# 1,线上机器上安装 tcpcopy
wget https://github.com/session-replay-tools/tcpcopy/archive/1.0.0.tar.gz
tar -zxf 1.0.0.tar.gz
cd tcpcopy-1.0.0
./configure --prefix=/opt/tcpcopy/ # 默认安装目录 /usr/local/tcpcopy
make
make install
1
2
3
4
5
6
2
3
4
5
6
# 2,tcpcopy 常用选项
选项 | 含义 |
---|---|
-x <transfer,> | 指定源服务器和目标服务器的ip和端口,<transfer,> 的格式可以为:sourceIP:sourcePort-targetIP:targetPort,… ,大多数情况下,sourceIP可以省略,两个'transfer'由','(逗号)分隔 |
-H <ip_addr> | 将本地主机的IP地址更改为给定的IP地址 |
-c <ip_addr,> | 发送到目标服务器时,将客户端IP地址更改为IP地址之一 |
-n <num> | 设置流量复制倍数,最大值为 1023。由于多次复制是基于修改端口号进行的,因此可能会出现端口冲突的情况,特别是在内网应用中,源ip很少,连接时间较短。因此复制倍数越小,tcpcopy将执行得更好 |
-f <num> | 当运行多个tcpcopy实例时,使用此参数控制端口号修改进程,减少端口冲突。对于不同的tcpcopy实例,<num> 的值应该不同,允许的最大值是1023 |
-m <num> | 设置tcpcopy允许使用的最大内存(以兆为单位),防止tcpcopy占用过多内存,影响在线系统。当内存超过这个限制时,tcpcopy 将自动退出。该参数仅在内核版本为2.6.32及以上时有效。默认为1024 |
-M <num> | MTU,最大传输单元,数据链路层能够传输的最大网络包大小,默认 1500) |
-D <num> | MSS,最大分段尺寸,网络包能够装下最大报文大小,默认 1460 |
-R <num> | 设置默认的 rtt 值 |
-U <num> | 设置用户会话池大小,单位为千字节,默认为 1,最大 63 |
-C <num> | tcpcopy 与 intercept 之间的并发连接数,默认为 2,最大值为 11 |
-s <server,> | intercept 服务列表,形如:ip_addr1:port1, ip_addr2:port2, ... |
-t <num> | 设置会话的超时时间。在超时时间后 tcpcopy 还没收到目标服务器的返回,该会话将被丢弃。当来自目标服务器的响应较慢或应用程序协议基于上下文时,应该设置更大的值。默认值 120 seconds. |
-k <num> | 设置会话保持的超时时间 |
-l <file> | 设置日志文件 |
-r <num> | 设置会话传输百分比 (integer range:1~100) |
-p <num> | 设置目标服务器的监听端口,默认值 36524. |
-P <file> | 设置 pid 存储的文件,仅用于 -d 选项下 |
-O | 仅回放全会话 |
-g | 慢慢回放 gradully |
-v | 版本 |
-h | 打印帮助并退出 |
-d | 以守护进程的方式运行 |
# 3,辅助机器上安装 intercept
yum -y install libpcap-devel # 在Unix-like系统上捕获网络数据包的库
wget https://github.com/session-replay-tools/intercept/archive/1.0.0.tar.gz
tar -zxf 1.0.0.tar.gz
cd intercept-1.0.0
./configure --prefix=/opt/tcpcopy/
make
make install
1
2
3
4
5
6
7
2
3
4
5
6
7
# 4,intercept 常用选项
选项 | 含义 |
---|---|
-i <device,> | 要侦听的网卡接口名称,通常是驱动程序名称后面跟着一个单元号,例如,第一个以太网接口为eth0 |
-F <filter> | 过滤规则(和 pcap 规则一样) |
-n <num> | 设置最大合并包的数量 |
-p <num> | 设置监听的 TCP 端口号,默认 36524 |
-s <num> | 为 intercept 设置哈希表的尺寸,默认 65536 |
-l <file> | 设置日志文件 |
-P <file> | 设置 pid 存储的文件,仅用于 -d 选项下 |
-b <ip_addr> | 监听接口 (默认 INADDR_ANY, 所有地址) |
-v | 版本 |
-h | 打印帮助并退出 |
-d | 以守护进程的方式运行 |
# 五、快速入门
- 假设 “61.135.233.160” 为目标服务器的 IP 地址;
- 假设 “61.135.233.161” 为辅助服务器的 IP 地址;
# 1,目标服务器设置路由
- 设置适当的路由命令,将目标服务器的响应报文路由到辅助服务器;
# 执行 route 命令将所有对 “62.135.200.x” 客户端的响应路由到辅助服务器 “61.135.233.161”
route add -net 62.135.200.0 netmask 255.255.255.0 gw 61.135.233.161
1
2
2
# 2,辅助服务器运行 intercept
- 在辅助服务器上运行 intercept,需要 root 权限或CAP_NET_RAW功能;
# 监听 eth0 网卡,监听 8080 端口的 tcp 包,以守护进程的方式运行
./intercept -i eth0 -F 'tcp and src port 8080' -d
1
2
2
# 3,线上服务器运行 tcpcopy
# 捕获当前服务器上 “80” 端口数据包,更改客户端IP地址为 “62.135.200.x" 中的一个
# 将这些数据包发送到目标服务器 ”61.135.233.160“ 的 ”8080“
# 连接辅助服务器 “61.135.233.161”,将响应数据包传递给 intercept
# ”-c" 参数是可选的,设置它是为了简化路由命令
# 流量复制比例为 2 倍
./tcpcopy -x 80-61.135.233.160:8080 -s 61.135.233.161 -c 62.135.200.x -n 2
1
2
3
4
5
6
2
3
4
5
6
# 六、注意事项
- 仅在 Linux 上测试通过(内核2.6或更高版本);
- TCPCopy 可能会丢失数据包,从而丢失请求;
- 需要
root
权限或CAP_NET_RAW
功能(例如setcap CAP_NET_RAW=ep tcpcopy
) - TCPCopy 现在仅支持客户端启动的连接;
- TCPCopy 不支持使用
SSL/TLS
的服务器应用程序的重放; - 有关 MySQL 会话重播,请参阅 https://github.com/session-replay-tools;
- 不应该辅助服务器上设置
ip_forward
为 true,否则无法充当黑洞;
# 七、可能存在的问题
# 1,捕获接口
- 默认情况下,TCPcopy 利用原始套接字输入接口在线上服务器上的网络层捕获数据包,系统繁忙时,系统内核可能会丢失一些数据包;
- 在执行 tcpcopy 的
./configure
时,如果使用--pcap-capture
配置,则 tcpcopy 可以在数据链路层捕获数据包,也可以过滤内核中的数据包; - 使用
PF_RING
,tcpcopy 在使用 pcap 捕获时会丢失更少的数据包; - 捕获请求的最佳方法是通过交换机镜像入口数据包,然后通过负载均衡器将巨大的流量划分到多台机器;
# 2. 发送接口
- 默认情况下,TCPcopy 利用原始套接字输出接口将网络层的数据包发送到目标服务器;
- 如果要避免
ip_conntrack
问题或获得更好的性能,在执行 tcpcopy 的./configure
时,如果使用--pcap-send
配置,然后使用适当的参数,tcpcopy 可以在数据链路层将数据包发送到目标服务器;
# 3,在前往目标服务器的途中
- 当数据包通过 tcpcopy 发送时,默认情况下,数据包中的源IP地址仍然是终端用户的IP地址,而不是在线服务器的IP地址,某些安全设备可能会将其视为无效或伪造的数据包并将其丢弃;
- 在这种情况下,使用 tcpdump 捕获目标服务器上的数据包时,不会捕获来自期待的终端用户的数据包;
- 要了解是否处于这种情况,可以选择同一网段中的目标服务器进行测试,如果数据包可以在同一网段中成功发送到目标服务器,但跨网段未成功发送,则数据包可能会中途丢弃;
- 为了解决这个问题,建议在同一网段的服务器上部署 tcpcopy、intercept 和目标应用程序;
- 在同一网段中的代理的帮助下,TCPcopy 可以将数据包发送到代理,然后代理将相应的请求发送到另一个网段中的目标服务器;
# 4,目标服务器的操作系统
- 目标服务器如果设置了
rpfilter
,将检查数据包中的源 IP 地址是否是伪造的,如果是,数据包将在网络层丢弃; - 如果目标服务器上的 tcpdump 可以捕获数据包,服务却无法收到请求,则应检查是否有任何相应的
rpfilter
设置,如果设置,则必须删除相关设置,以使数据包通过网络层; - 还有其他原因导致 tcpcopy 无法正常工作,例如 iptables 设置问题;
# 5,目标服务器上的服务
- 目标服务器上的服务可能无法及时处理所有请求;
- 一方面,服务中的错误可能会使请求长时间没有响应;
- 另一方面,TCP 层以上的某些协议可能只处理套接字缓冲区中的第一个请求,而将套接字缓冲区中的剩余请求保留为未处理;
参考文章
[1] https://github.com/session-replay-tools/tcpcopy (opens new window)
[2] https://cloud.tencent.com/developer/article/1537496 (opens new window)
编辑 (opens new window)
上次更新: 2024/08/18, 23:14:26