Zookeeper通信协议

7

我需要使用tcpdump来调试我的kafka消费者和zookeeper之间交换的数据。我已经阅读了zookeeper文档,但没有找到有关zookeeper通信协议的文章,也就是说,在删除头部后,我使用wireshark获得了以下数据转储。如何解释数据部分?

Frame 1: 78 bytes on wire (624 bits), 78 bytes captured (624 bits)
Ethernet II, Src: 22:00:0a:xx:xx:xx (22:00:xx:xx:xx:xx), Dst: fe:ff:xx:xx:xx:xx (fe:ff:ff:xx:xx:xx)
Internet Protocol Version 4, Src: 10.234.xxx.xxx, Dst: 10.231.xxx.xxx
Transmission Control Protocol, Src Port: 51720 (51720), Dst Port: 2181 (2181), Seq: 1, Ack: 1, Len: 12
Data (12 bytes)
    Data: 00000008fffffffe0000000b
    [Length: 12]

“竞争对手”声称:“Zookeeper拥有自己定制的Jute RPC协议,这是完全独特于Zookeeper的,并限制了它支持的语言绑定。” https://etcd.io/docs/v3.4.0/learning/why/ 我了解到Jute正在重新考虑。https://issues.apache.org/jira/browse/ZOOKEEPER-102 - Nemo
1个回答

13

很抱歉,我不知道有没有方便的文档详细描述Apache ZooKeeper的传输协议。我们内部使用一个名为Jute的框架,它基于最初从Apache Hadoop适配的代码。该框架允许定义结构化记录,基于这些定义生成代码,然后提供由ZooKeeper其他代码调用的序列化/反序列化例程。

Jute记录定义在此处可见:

https://github.com/apache/zookeeper/blob/release-3.4.9/src/zookeeper.jute

处理这些记录定义的Jute框架代码在以下位置可见:

https://github.com/apache/zookeeper/tree/release-3.4.9/src/java/main/org/apache/jute

我认为了解传输协议的深入方法是挖掘这段代码。

在挖掘几层原始套接字处理代码(根据配置使用NIO或Netty)后,实际反序列化有效负载的工作发生在ZooKeeperServer#processPacket(ServerCnxn,ByteBuffer)中:

https://github.com/apache/zookeeper/blob/release-3.4.9/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java#L941

这是它反序列化一个RequestHeader的地方,它是该协议所有消息前面的元数据的通用头。 RequestHeader的定义在此处显示:

https://github.com/apache/zookeeper/blob/release-3.4.9/src/zookeeper.jute#L88-L91

我们可以看到它由2个4字节整数字段组成:连接ID和消息类型。类型值在此处定义:ZooDefs

https://github.com/apache/zookeeper/blob/release-3.4.9/src/java/main/org/apache/zookeeper/ZooDefs.java#L28

了解所有这些后,让我们回到你的数据包捕获并尝试理解它:

Data: 00000008fffffffe0000000b

00000008 - payload length
fffffffe - connection ID
0000000b - op code ("ping")

在每条消息的前面(甚至在 RequestHeader 前面),都会有负载长度。在这里,我们看到了一个长度为8个字节。

接下来的4个字节是连接 ID,fffffffe

最后的4个字节是操作码,0000000b(或十进制的11)。通过阅读 ZooDefs,我们可以看到这是“ping”操作。 “ping” 操作用于客户端和服务器之间的定期心跳。在“ping”操作中不需要额外的负载数据,所以这是本数据包的结尾,它后面没有其他数据。对于不同的操作,负载中将会有额外的数据,表示操作的参数。

希望这可以帮助。


1
我查阅了文档,但不明白元数据是如何附加的?我们在哪里指定特定消息的请求类型?抱歉,我一直在考虑类似于TCP数据包的头部解构。不过文档还是有帮助的。 - ankshah
@ankshah,我刚刚编辑了我的答案,提供了更多与ZooKeeper代码库相关的链接,并利用这些信息详细介绍了您在问题中发布的特定数据包捕获。希望对您有所帮助。 - Chris Nauroth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接