利用tcpcopy引流做模拟在线测试
2012-05-29 18:46:44 来源:我爱运维网 评论:0 点击:
一、工具介绍
Tcpcopy是一个分布式在线压力测试工具,可以将线上流量拷贝到测试机器,实时的模拟线上环境,达到在程序不上线的情况下实时承担线上流量的效果,尽早发现bug,增加上线信心。
Tcpcopy是由网易技术部于2011年9月开源的一个项目,现在已经更新到0.4版本。
与传统的压力测试工具(如:abench)相比,tcpcopy的最大优势在于其实时及真实性,除了少量的丢包,完全拷贝线上流量到测试机器,真实的模拟线上流量的变化规律。
二、Tcpcopy的原理
1.流程
现在以nginx作为前端说明tcpcopy的原理:
上图中左边是线上前端机,右边是测试前端机。线上前端机开启tcpcopy客户端(tcpcopy进程),测试前端机开启tcpcopy服务端(interception进程),且两台机器上都启动了nginx服务。
Tcpcopy拷贝一次流量访问的步骤如下:
① 一个访问到达线上前端机;
② socket包在ip层被拷贝了一份传给tcpcopy进程;
③ tcpcopy修改包的目的及源地址,发给测试前端机;
④ 拷贝的包到达测试前端机;
⑤ 测试前端机的nginx处理访问,并返回结果;
⑥ 返回结果在ip层被截获、丢弃,由intercpetion拷贝返回结果的ip header返回;
⑦ ip header被发送给线上前端机的tcpcopy进程。
1.代码分析
1) 首先,在链路层或者IP层,在把包交到上一层之前,系统会检查有没进程创建了socket(AF_PACKET,SOCK_DGRAM,…)或socket(AF_INET,SOCK_RAW,…)等类型的套接字(即原始套接字sock_raw),如果有,这个包就会被复制一份并发送到这个socket的缓冲区。tcpcopy就是通过这种方式来复制访问流量的。上述的两种抓包方式,前者工作在数据链路层,后者工作在IP层。在tcpcopy中不同版本所使用的抓包函数不同,在0.3版本中是:
int sock = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_IP));
而在0.4版本中,用的是:
int sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
以上两个函数分别工作在链路层和IP层,前者会把进来和出去的包都抓取到,后者只 抓取到进来的包。
2) Tcpcopy在发送拷贝的数据包的时候,使用了如下socket:
sock = socket(AF_INET, SOCK_RAW,IPPROTO_RAW);
并对这个socket设置了IP_HDRINCL:
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n));
因此网络层不会再增加ip header. 发送之前更改了包的目的ip和端口:
tcp_header->dest = remote_port;
ip_header->daddr = remote_ip;
最后调用sendto函数发送包到测试前端机:
send_len = sendto(sock,(char *)ip_header,tot_len,0,
(struct sockaddr *)&toaddr,sizeof(toaddr));
3) 在测试前端机上加载了ip_queue模块,并设置iptables规则:
iptables -I OUTPUT -p tcp –sport 80 -j QUEUE
复制的访问流量到达测试前端机上的nginx,nginx处理并返回结果,这个结果包在IP层会被前面所设置的iptables规则匹配发往目标(target)QUEUE。而QUEUE是由ip_queue模块实现。下一步这个匹配包就会被内核经过netlink socket发往用户空间的程序(在这是tcpcopy的服务端interception进程)。
netlink socket是内核与用户进程之间的一种通信机制,是网络应用程序与内核通信的最常用的接口,可以用来配置网络的各个方面(比如包的过滤)。
interception用如下方式创建netlink socket:
int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_FIREWALL);
NETLINK_FIREWALL协议有三种消息类型:IPQM_MODE,IPQM_PACKET,IPQM_VERDICT.
内核通过一个IPQM_PACKET消息将刚才截获的返回结果包发送到interception,interception给内核发送一个IPQM_VERDICT消息告诉内核对这个包的裁决结果(DROP,ACCEPT,etc.)。tcpcopy通过这样的办法将测试前端机上nginx返回的结果截获丢弃,并由interception返回一个ip header.相应代码实现如下:
拷贝结果包的ip header,发送:
struct receiver_msg_st msg;
...
memset(&msg,
0
,sizeof(struct receiver_msg_st));
memcpy((
void
*) &(msg.ip_header),ip_header,sizeof(struct iphdr));
memcpy((
void
*) &(msg.tcp_header),tcp_header,sizeof(struct tcphdr));
...
send(sock,(
const
void
*)msg,sizeof(struct receiver_msg_st),
0
);
interception向内核发送IPQM_VERDICT消息报告裁决结果:
struct nlmsghdr* nl_header=(struct nlmsghdr*)buffer;
struct ipq_verdict_msg *ver_data = NULL;
struct sockaddr_nl addr;
nl_header->nlmsg_type=IPQM_VERDICT;
上一篇:第一页
下一篇:WebCDN流量及QOS异常故障RC查找与经验分享
评论排行
- ·Windows(Win7)下用Xming...(92)
- ·使用jmx client监控activemq(20)
- ·Hive查询OOM分析(14)
- ·复杂网络架构导致的诡异...(8)
- ·使用 OpenStack 实现云...(7)
- ·影响Java EE性能的十大问题(6)
- ·云计算平台管理的三大利...(6)
- ·Mysql数据库复制延时分析(5)
- ·OpenStack Nova开发与测...(4)
- ·LTPP一键安装包1.2 发布(4)
- ·Linux下系统或服务排障的...(4)
- ·PHP发布5.4.4 和 5.3.1...(4)
- ·RSYSLOG搭建集中日志管理服务(4)
- ·转换程序源码的编码格式[...(3)
- ·Linux 的木马程式 Wirenet 出现(3)
- ·Nginx 发布1.2.1稳定版...(3)
- ·zend framework文件读取漏洞分析(3)
- ·Percona Playback 0.3 development release(3)
- ·运维业务与CMDB集成关系一例(3)
- ·应该知道的Linux技巧(3)