Bolt 协议握手规范

所有 Bolt 连接均以握手开始,以协商使用哪种版本的消息协议。协商成功后,约定的消息协议将在连接的剩余生命周期内接管该连接。握手本身不区分版本。

Bolt 是一种主要用于在数据库服务器上执行查询的客户端-服务器协议。通信通过请求-响应交换进行,方式与 HTTP 非常相似。然而,与 HTTP 不同的是,Bolt 连接是有状态的。

除非另有说明,否则字节值均使用十六进制表示法。

字节序

Bolt 要求所有可能受字节序影响的值都应使用网络字节序(也称为大端字节序)进行传输。这意味着值的最高有效部分首先被写入网络或内存空间,而最低有效部分最后被写入。

连接与断开连接

Bolt 通信旨在通过 TCP 连接进行。默认端口为 TCP 7687,但也可以使用任何端口。

Bolt 连接没有正式的关闭程序。任何一方都可以随时在 TCP 层关闭连接。客户端和服务器都应为此做好准备,并应进行相应的处理。

握手

在连接成功后,客户端必须立即发起握手。此握手是一个固定的交换过程,用于确定后续使用的消息协议版本。

Bolt 标识

握手的第一部分用于向服务器标识这是一个 Bolt 连接。它应由客户端在建立成功连接后立即发送,且不需要服务器响应。

该标识由以下四个字节组成

C: 60 60 B0 17

版本协商

在标识之后,会发生一次小的客户端-服务器交换,以确定使用哪种消息协议版本。在此过程中,客户端会提交恰好 四个协议版本,每个版本编码为一个 大端 32 位无符号整数,总计 128 位。如果交换中需要的版本少于四个,则可以使用零作为占位符。如果找到了服务器支持的版本,响应将包含该版本,编码为 单个 32 位整数。如果未找到匹配项,则返回零值,随后服务器将立即关闭连接。

在此交换中,零值(四个零字节)始终表示“无协议版本”。对于客户端,如果已知的协议版本少于四个,则可用作填充项。对于服务器,这表示未找到匹配的版本。

服务器应假设客户端请求中包含的版本已按偏好顺序发送。因此,如果存在多个版本匹配,应选择第一个匹配项。

示例:客户端了解 Bolt 协议版本 1,服务器响应版本 1。
C: 60 60 B0 17
C: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
S: 00 00 00 01
示例:客户端了解 Bolt 协议版本 1 和 2,服务器响应版本 2。
C: 60 60 B0 17
C: 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00
S: 00 00 00 02
示例:客户端了解 Bolt 协议版本 1、2 和 3,服务器响应版本 2。
C: 60 60 B0 17
C: 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00 00
S: 00 00 00 02
示例:客户端仅了解 Bolt 协议版本 3,但服务器响应无版本,表示服务器不支持与该客户端通信。
C: 60 60 B0 17
C: 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00
S: 00 00 00 00

Bolt 版本 5.7

Bolt 版本 5.7 引入了一种新的握手方案:Manifest v1

VarInt (可变长度整数)

VarInt 以 7 位为一组进行传输,最低有效位在前。每个字节中的最高有效位用作延续位,表示后续还有更多数据。因此,它不应被视为解码值的一部分。

十六进制编码 二进制解码(大端) 十进制解码

01

0000 0001

1

7F

0111 1111

127

FF 82 71

0001 1100 0100 0001 0111 1111

1851775

让我们解析最后一个示例

# Encoded in hexadecimal
FF 82 71
# Encoded in binary
1111 1111  1000 0010  0111 0001
# These are the continuation bits specifying how many bytes to read
1... ....  1... ....  0... ....
# Bits of the actual value (in 7-bit groups in little-endian order)
 111 1111   000 0010   111 0001
 ========   ^^^^^^^^   ~~~~~~~~
# Convert to big-endian (if target machine is big-endian)
 111 0001   000 0010   111 1111
 ~~~~~~~~   ^^^^^^^^   ========
# Concatenate bits for the final (big-endian) binary representation
0001 1100  0100 0001  0111 1111
   ~~~~~~~~~~^^^^^^^^^^========

握手 Manifest v1

客户端可以使用特殊版本 00 00 01 FF 替换 4 个 32 位版本请求之一。其中前两个字节保留,下一个字节为 Manifest 版本(此处为 v1),最后一个字节 FF 表示这是一个 Manifest 样式的握手请求。

如果服务器接受该请求,它将响应 00 00 01 FF,随后是:

  • 一个 VarInt N(最大 64 位无符号整数)

  • 一个长度为 N 的支持的 Bolt 版本列表,采用 Bolt 4.3 样式(每个 4 字节)。

  • 一个 VarInt CAPABILITIES(最大 64 位无符号整数),这是一个用于供应商特定协议修正的保留位掩码。

客户端可以选择任何提供的版本并回复:

  • 所选版本,采用 Bolt 4.0 样式(4 字节,不得包含范围)。

  • 一个 VarInt CAPABILITIES,选择所提供功能的一个子集(或全部)。

由于客户端完成握手部分后不期望有服务器响应,因此客户端可以将该握手与第一条 Bolt 消息流水线处理。
示例
C: 60 60 B0 17                                         # (1)
C: 00 00 01 FF  00 00 04 04  00 00 00 03  00 00 00 02  # (2)
S: 00 00 01 FF                                         # (3)
S: 02                                                  # (4)
S: 00 02 08 05                                         # (4a)
S: 00 04 04 04                                         # (4b)
S: 09                                                  # (5)
C: 00 00 07 05                                         # (6)
C: 08                                                  # (7)
  1. Bolt 标识

  2. 客户端请求(按偏好顺序)

    • Manifest v1

    • Bolt 版本 4.4 - 4.0 中的最高可用版本

    • Bolt 版本 3

    • Bolt 版本 2

  3. 服务器选择 Manifest v1

  4. 服务器声明有 2 个支持的版本(范围)可用

    1. Bolt 版本 5.8 - 5.6

    2. Bolt 版本 4.4 - 4.0

  5. 服务器提供功能位 1 和 4(位掩码 0000 1001

  6. 客户端选择 Bolt 版本 5.7

  7. 客户端选择功能位 4(位掩码 0000 1000

Bolt 版本 4.3

在 Bolt 4.3 版本中,版本方案支持次要版本范围。前 8 位保留。接下来的 8 位表示在指定的次要版本(接下来的 8 位)和主要版本(接下来的 8 位)之下,连续支持的次要版本数量。

范围不能跨越多个主要版本。

版本 4.3 外加两个先前次要版本(4.2 和 4.1)的示例
00 02 03 04
客户端了解五个 Bolt 版本(3、4.0、4.1、4.2 和 4.3),服务器响应 4.1 的示例
C: 60 60 B0 17
C: 00 03 03 04 00 00 01 04 00 00 00 04 00 00 00 03
S: 00 00 01 04

客户端必须显式指定 4.3 之前的所有版本,因为仅支持这些协议版本的服务器可能不支持范围。该示例利用了 Bolt 4.1 和 4.2 是等效的事实,仅提供 4.3、4.2、4.0 和 3,但指定了一个范围 (4.3-4.0),以防服务器支持范围。

Bolt 版本 4.0

在 Bolt 4.0 版本中,版本方案支持主要和次要版本号。前 16 位保留。8 位表示次要版本。8 位表示主要版本。

版本 4.1 的示例
00 00 01 04
客户端了解三个 Bolt 版本(3、4.0 和 4.1),服务器响应 4.1 的示例。
C: 60 60 B0 17
C: 00 00 01 04 00 00 00 04 00 00 00 03 00 00 00 00
S: 00 00 01 04
© . This site is unofficial and not affiliated with Neo4j, Inc.