动物园管理员通信协议
Zookeeper communication protocol
我需要使用 tcpdump 调试我的 kafka 消费者和 zookeeper 之间交换的数据。我浏览了 zookeeper 文档,但找不到任何关于 zookeeper 通信协议的文章,即我在删除 headers 后使用 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]
抱歉,我不知道有任何方便的文档详细描述了 Apache ZooKeeper 有线协议。在内部,我们的代码库使用一个名为 Jute 的框架,该框架基于最初改编自 Apache Hadoop 的代码。该框架允许定义结构化记录,根据这些定义生成代码,然后提供 serialization/deserialization 由其余 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)
:
这是它反序列化 RequestHeader
的地方,它是所有协议消息前面的通用 header 元数据。 RequestHeader
的定义如下所示:
https://github.com/apache/zookeeper/blob/release-3.4.9/src/zookeeper.jute#L88-L91
我们可以看到它由 2 个 4 字节整数字段组成:一个连接 ID,后跟消息类型。类型值在 ZooDefs
此处定义:
了解了所有这些,让我们回到您的数据包捕获并尝试理解它:
Data: 00000008fffffffe0000000b
00000008 - payload length
fffffffe - connection ID
0000000b - op code ("ping")
在每条消息的前面(甚至在RequestHeader
之前),都有有效负载的长度。这里我们看到长度为 8 个字节。
接下来的4个字节是连接ID,fffffffe
。
最后 4 个字节是操作码,0000000b
(或十进制的 11)。读取ZooDefs
,我们可以看出这是"ping"操作。 "ping" 操作用于客户端和服务器之间的周期性心跳。 "ping" 操作的有效负载中不需要额外的数据,所以这是这个数据包的结尾,后面没有额外的数据。对于不同的操作,负载中会有额外的数据,代表操作的参数。
希望对您有所帮助。
我需要使用 tcpdump 调试我的 kafka 消费者和 zookeeper 之间交换的数据。我浏览了 zookeeper 文档,但找不到任何关于 zookeeper 通信协议的文章,即我在删除 headers 后使用 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]
抱歉,我不知道有任何方便的文档详细描述了 Apache ZooKeeper 有线协议。在内部,我们的代码库使用一个名为 Jute 的框架,该框架基于最初改编自 Apache Hadoop 的代码。该框架允许定义结构化记录,根据这些定义生成代码,然后提供 serialization/deserialization 由其余 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)
:
这是它反序列化 RequestHeader
的地方,它是所有协议消息前面的通用 header 元数据。 RequestHeader
的定义如下所示:
https://github.com/apache/zookeeper/blob/release-3.4.9/src/zookeeper.jute#L88-L91
我们可以看到它由 2 个 4 字节整数字段组成:一个连接 ID,后跟消息类型。类型值在 ZooDefs
此处定义:
了解了所有这些,让我们回到您的数据包捕获并尝试理解它:
Data: 00000008fffffffe0000000b
00000008 - payload length
fffffffe - connection ID
0000000b - op code ("ping")
在每条消息的前面(甚至在RequestHeader
之前),都有有效负载的长度。这里我们看到长度为 8 个字节。
接下来的4个字节是连接ID,fffffffe
。
最后 4 个字节是操作码,0000000b
(或十进制的 11)。读取ZooDefs
,我们可以看出这是"ping"操作。 "ping" 操作用于客户端和服务器之间的周期性心跳。 "ping" 操作的有效负载中不需要额外的数据,所以这是这个数据包的结尾,后面没有额外的数据。对于不同的操作,负载中会有额外的数据,代表操作的参数。
希望对您有所帮助。