有时,在对副本集的健康状况进行故障排除时,我想专门过滤掉心跳数据包,跟踪它们发出的信息,以及随后的回复(或缺少回复),而没有其他数据之间流动的所有噪音套。
不幸的是,这些数据包的结构与普通命令/查询和响应的结构非常相似。尽管Wireshark有解析器,可以让我接触到 MongoDB 有线协议,但我不能使用 tcpdump 的这种技术从源头过滤掉数据包。
那么,问题来了——如何过滤 tcpdump 中的 MongoDB 副本集心跳?
有时,在对副本集的健康状况进行故障排除时,我想专门过滤掉心跳数据包,跟踪它们发出的信息,以及随后的回复(或缺少回复),而没有其他数据之间流动的所有噪音套。
不幸的是,这些数据包的结构与普通命令/查询和响应的结构非常相似。尽管Wireshark有解析器,可以让我接触到 MongoDB 有线协议,但我不能使用 tcpdump 的这种技术从源头过滤掉数据包。
那么,问题来了——如何过滤 tcpdump 中的 MongoDB 副本集心跳?
在此文档的基础上,首先我们需要确定我们的识别特征是什么,以便过滤器成功并且只挑选出心跳。然后,我们需要获取该标识符的十六进制表示。从出站心跳本身(本质上只是一个查询/命令)开始,它是一个管理命令,包含以下字符串:
现在我们有了识别字符串,我们需要弄清楚在 TCP 内部的位置。偏移量计算如下:
TCP 的 32 个字节让您使用MongoDB 有线协议,然后:
因此总偏移量为: (32+4+4+4+4+4+11+4+4+4+1) = 76 字节
因此,您会认为需要这样的东西:
遗憾的是,tcpdump 一次最多只能匹配 4 个字节,因此您实际上需要将其分解为 4 x 4 字节块并使用逻辑 AND 来组合匹配项:
这涵盖了心跳的出站部分,但是回复呢?
值得庆幸的是,心跳上的回复更容易匹配——我们正在寻找文档的 rs:true 部分,它的翻译如下,很容易适应 4 个字节:
以类似的方式计算偏移量(唯一真正的区别是 8 字节的游标 ID 而不是 11 字节的集合名称)我们得到 73 字节的偏移量,这就得到了这个过滤器:
最后,让我们把它们放在一起,并添加一些我喜欢的 tcpdump 选项。最后我们得到这个命令:
(在 Mac OS X 和 Linux 上使用 MongoDB 2.4.4 成功测试)
当然,这也可以应用得更普遍,你只需要制定出合适的匹配标准、偏移量和字节匹配即可。
作为参考,您可以使用相同的标准,但语法略有不同,以在 Wireshark 中测试这种类型的过滤。上述标准的等效 Wireshark 过滤器是: