Skip to main content

tcpkit 介绍

· 7 min read

一年即将过去,翻了一下博客发现更新频率比月经还来得稀疏,内疚到前列腺都萎缩了。

转入正题,本篇博客主要是分享一个自己日常用的比较多工具 tcpkit, 该工具用途主要是用来抓包和快速的分析数据包。

代码地址: git-hulk/tcpkit

1) 为什么要用它

现在抓包不有 tcpdump 么? 分析包不是有很牛逼和方便的 wireshark 么? 当然我也不是闲到前列腺发炎,浪费时间造出这么个正方形的轮子。

造这个轮子的原因是这样,我们偶尔会遇到线上访问资源(redis, mc..) 出现耗时比较长的情况。如果是 tcpdump 可以用来抓包,但如果请求量很大又是偶发,我要这么知道哪个连接慢了? 这个时候 wireshark 也是帮不上忙的(因为它不知道哪个数据是请求,那个数据包是响应,也就没办法统计延时)。

这时候 tcpkit 就可以派上用场了。

2) 初见

tcpkit 的初衷:「 让使用者可以想分析普通内存数据一样,可以写代码轻松的分析 udp/tcp 包 」

比如,我们默认的脚本就是 1 行 lua 代码就可以打印数据包内容,具体见 example.lua:

function process_packet(item)
-- sync,ack 这种包长度为 0, 我们忽略掉
if item.len > 0 then
print(item.payload)
end
end

每抓到一个数据包都会回调 process_packet, 然后把数据包内容传递进来,这样用户使用 lua 代码来定制分析的需求了。像上面的回调函数,就是什么都不分析就看看内容。

3) 上手

那么问题来了,我要怎么玩这个东西呢。按照下面来就可以了...

$ git clone https://github.com/git-hulk/tcpkit.git /* 首先... 我得先拿到代码*/
$ cd tcpkit/src
$ make /* make install 是可选,要不要安装到标准的路径 */

本目录就生成了一个 tcpkit 的二进制文件,那么你就可以开始玩它了,姿势可以参考 README

主要的几个参数说明:

-i 指定抓包的网卡,默认是 any,就是所有网卡,但有些系统不支持

-p 指定抓包的端口

-s 如果是在客户端抓包,可以定向抓到某个服务的包

-S 指定处理脚本路径,固定回调 process_packet 这个函数

我们用 redis/mc 延时统计的脚本作为例子,要客户端看看请求 Redis 到返回耗时多长时间。

假设 redis ip: 192.168.1.1, 端口: 6379, 客户端: 192.168.1.2, 那么就就下面这样启动:

sudo ./tcpkit -s 192.168.1.1 -p 6379 -S ../scripts/redis_mc_monitor.lua

结果大概如下(ip端口是不对应的):

2020-02-06 23:01:39.706782 127.0.0.1:54484 => 127.0.0.1:6379 | 0.270 ms | GET test_key 
2020-02-06 23:01:39.712727 127.0.0.1:54540 => 127.0.0.1:6379 | 0.012 ms | PING
2020-02-06 23:01:40.004345 127.0.0.1:54554 => 127.0.0.1:6379 | 0.187 ms | SET a b

第一列是响应的时刻,第二列和第三列分别是客户端和服务端连接的 ip 和端口,第三列是延时,最后一列是请求

如果跑在服务端,统计就是服务端处理的时间,耗时是包进来到出去的时间差。

NOTE: 在服务端,不需要指定 -s 这个 server ip, 只需要指定端口和脚本

4) 简单统计原理

Q: 请求和响应要怎么对应起来?

A: 这个问题如果是变成怎么知道两个数据包是来自同一个连接就简单多了。

「 根据 tcp/ip 的ip和端口四元组就可以确定数据包是否同一个连接了 」

Q: 请求和响应怎么对应?

对于 Redis/mc 这种,对于同一个连接都是发出请求,然后必须等待响应才能下一个请求(不考虑 redis 的 pipeline),那这个就好办了。

第一种情况: 在客户端抓包,如果源 ip 为本地ip, 那么说明这个数据包是发出去的,也就是请求数据包。反过来就是响应包。

第二种情况: 在服务端抓包,跟上面刚好相反,如果是源 ip 是本地 ip, 说明数据是出去的,也就是响应包。

那么只要知道是同一个连接,而且知道请求还是响应那么就可以统计延时了。上面说到如果是 redis pipeline 这种一来一往的数据包就要想其他方法了。

5) 脚本

这个不需要深入了解 lua, 只要简单会应用就可以。tcpkit/scripts 目录提供了 rdis/mc/dns/kafka 的延时统计脚本,kafka 还有些问题,待修改。

如果是私有协议或者其他更多复杂的协议,需要自己实现。

6) END

是否还有其他姿势? 欢迎分享。

最后祝玩得开心。

代码地址: git-hulk/tcpkit