tcprstat是percona用来监测mysql响应时间的。不过对于任何运行在TCP协议上的响应时间,都可以用。本文主要做源码分析,如何使用tcprstat请大家查看博文《tcprstat分析服务的响应速度利器》
tcprstat和tcpdump一样,使用libpcap库进行抓包,然后再通过程序对抓取的tcp包进行分析。
tcprstat对tcp包分析的大概流程如下:
<img src="//pic.ikafan.com/imgp/L3Byb3h5L2h0dHAvd3d3LmJvNTYuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE0LzA2L3Byb2Nlc3NfaXAuanBn.jpg" alt="process_ip" width="552" height="313" class="alignnone size-full wp-image-396" /></a><br /> 1、通过分析来源ip和目标ip,看那个ip是本地ip,来判断是进来的包(请求包)还是出去的包(响应包)。
2、如果包的数据大小为0,那么就跳过,不再处理。数据大小为0的视为tcp控制包。
3、如果数据包为进来的包(请求包),则插入一条记录到哈希表。
4、如果数据包为出去的包(响应包),则用现在的包和之前插入哈希表中的响应包做时间差计算。并把之前的包在哈希表中删除。
数据包分析的代码在process-packet.c文件中,方法如下:
int
process_ip(pcap_t *dev, const struct ip *ip, struct timeval tv) {
char src[16], dst[16], *addr;
int incoming;
unsigned len;
addr = inet_ntoa(ip->ip_src);
strncpy(src, addr, 15);
src[15] = '\0';
addr = inet_ntoa(ip->ip_dst);
strncpy(dst, addr, 15);
dst[15] = '\0';
if (is_local_address(ip->ip_src))
incoming = 0;
else if (is_local_address(ip->ip_dst))
incoming = 1;
else
return 1;
len = htons(ip->ip_len);
switch (ip->ip_p) {
struct tcphdr *tcp;
uint16_t sport, dport, lport, rport;
unsigned datalen;
case IPPROTO_TCP:
tcp = (struct tcphdr *) ((unsigned char *) ip + sizeof(struct ip));
#if defined(__FAVOR_BSD)
sport = ntohs(tcp->th_sport);
dport = ntohs(tcp->th_dport);
datalen = len - sizeof(struct ip) - tcp->th_off * 4; // 4 bits offset
#else
sport = ntohs(tcp->source);
dport = ntohs(tcp->dest);
datalen = len - sizeof(struct ip) - tcp->doff * 4;
#endif
// Capture only "data" packets, ignore TCP control
if (datalen == 0)
break;
if (incoming) {
lport = dport;
rport = sport;
inbound(tv, ip->ip_dst, ip->ip_src, lport, rport);
}
else {
lport = sport;
rport = dport;
outbound(tv, ip->ip_src, ip->ip_dst, lport, rport);
}
break;
default:
break;
}
return 0;
}
ps:在这个文件中,process_packet 方法用户获取头信息。
时间: 2024-10-30 03:13:11