OpenWire 版本 2 规范
连接性 > 协议 > OpenWire > OpenWire 版本 2 规范
OpenWire 版本 2 不是最新版本。
本文引用了 OpenWire V2,它已不再是最新版本。本文中的格式和编码规则对后续的 OpenWire 版本仍然有效,但后续版本在 OpenWire 命令中定义了其他字段。本文中显示的默认设置可能不反映当前默认设置,请参阅 此页面 获取最新的默认 OpenWire 设置。
概述
OpenWire 用于将对象编组到字节数组并恢复。我们将编组后的对象称为命令。
TCP 网络连接将在流上看到多个连续的命令。命令没有以任何方式分隔,并且大小可变。
+---------+ +---------+ +---------+
| command | | command | .... | command |
+---------+ +---------+ +---------+
编码命令中使用的所有数据基本类型均以大端序/网络字节序编码。
基本类型和编码
| | | | | |
+----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+
| byte | | | char | | | short | | | int | | | long | | | float | | | double |
+----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+
| 1 octect | | | 2 octects | | | 2 octects | | | 4 octects | | | 8 octects | | | 4 octects | | | 8 octects |
+----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+ | +-----------+
| | | | | |
线格式协商
OpenWire 是可扩展的,因为它支持添加新的编码选项,同时仍然与协议的先前版本向后兼容。每个 OpenWire 协议会话最初都以关闭所有编码选项并使用版本 1 命令编组器开始。两个节点之间交换了初始 WIREFORMAT_INFO 命令,以便可以启用其他编码功能。如果双方都请求启用编码功能,则该功能将被启用。使用的命令编组器将是它们都支持的最高版本。
+-------------------------+ +---------+ +---------+ +---------+
| WIREFORMAT_INFO command | | command | | command | .... | command |
+-------------------------+ +---------+ +---------+ +---------+
命令编码
每个命令都按如下方式编码
命令编码
[=If SizePrefixDisabled =]
[ option is not enabled. ]
[ +------+ ] +------+-------------------------+
[ | size | ] | type | command-specific-fields |
[ +------+ ] +------+-------------------------+
[ | int | ] | byte | (size-1) octects |
[ +------+ ] +------+-------------------------+
[========================]
字段 | 描述 |
---|---|
大小 | 保存命令中后续的字节数 |
类型 | 命令类型标识符 |
特定于命令的字段 | 命令的数据。它的编码取决于使用的类型 |
如果命令类型没有任何特定于命令的内容,则大小为 1。
在每个命令之前添加大小是为了帮助进行非阻塞 IO 处理,以便接收方可以轻松确定何时已收到整个命令并可以进行处理。但是,找出命令的大小需要在发送方进行额外的缓冲,并且如果接收方正在进行阻塞 IO,则不需要这样做。如果在交换了 WIREFORMAT_INFO 数据包之后启用了 SizePrefixDisabled 选项,则每个后续命令都不会带上前缀大小。
命令类型
类型标识符 | 命令 |
---|---|
1 | WIREFORMAT_INFO |
2 | BROKER_INFO |
3 | CONNECTION_INFO |
4 | SESSION_INFO |
5 | CONSUMER_INFO |
6 | PRODUCER_INFO |
7 | TRANSACTION_INFO |
8 | DESTINATION_INFO |
9 | REMOVE_SUBSCRIPTION_INFO |
10 | KEEP_ALIVE_INFO |
11 | SHUTDOWN_INFO |
12 | REMOVE_INFO |
14 | CONTROL_COMMAND |
15 | FLUSH_COMMAND |
16 | CONNECTION_ERROR |
17 | CONSUMER_CONTROL |
18 | CONNECTION_CONTROL |
21 | MESSAGE_DISPATCH |
22 | MESSAGE_ACK |
23 | ACTIVEMQ_MESSAGE |
24 | ACTIVEMQ_BYTES_MESSAGE |
25 | ACTIVEMQ_MAP_MESSAGE |
26 | ACTIVEMQ_OBJECT_MESSAGE |
27 | ACTIVEMQ_STREAM_MESSAGE |
28 | ACTIVEMQ_TEXT_MESSAGE |
30 | RESPONSE |
31 | EXCEPTION_RESPONSE |
32 | DATA_RESPONSE |
33 | DATA_ARRAY_RESPONSE |
34 | INTEGER_RESPONSE |
40 | DISCOVERY_EVENT |
50 | JOURNAL_ACK |
52 | JOURNAL_REMOVE |
53 | JOURNAL_TRACE |
54 | JOURNAL_TRANSACTION |
55 | DURABLE_SUBSCRIPTION_INFO |
60 | PARTIAL_COMMAND |
61 | PARTIAL_LAST_COMMAND |
65 | REPLAY |
70 | BYTE_TYPE |
71 | CHAR_TYPE |
72 | SHORT_TYPE |
73 | INTEGER_TYPE |
74 | LONG_TYPE |
75 | DOUBLE_TYPE |
76 | FLOAT_TYPE |
77 | STRING_TYPE |
78 | BOOLEAN_TYPE |
79 | BYTE_ARRAY_TYPE |
90 | MESSAGE_DISPATCH_NOTIFICATION |
91 | NETWORK_BRIDGE_FILTER |
100 | ACTIVEMQ_QUEUE |
101 | ACTIVEMQ_TOPIC |
102 | ACTIVEMQ_TEMP_QUEUE |
103 | ACTIVEMQ_TEMP_TOPIC |
110 | MESSAGE_ID |
111 | ACTIVEMQ_LOCAL_TRANSACTION_ID |
112 | ACTIVEMQ_XA_TRANSACTION_ID |
120 | CONNECTION_ID |
121 | SESSION_ID |
122 | CONSUMER_ID |
123 | PRODUCER_ID |
124 | BROKER_ID |
命令字段编码
所有 OpenWire 命令在编码其字段时都使用相同的算法。该算法限制命令使用以下类型的字段
- Java 基本类型
- 字符串
- 字节数组
- N 个大小的字节数组
- Throwable
- 嵌套 OpenWire 命令
- 嵌套 OpenWire 命令数组
- 缓存的嵌套 OpenWire 命令
请注意,OpenWire 命令可以在其字段中嵌套其他 OpenWire 命令。必须注意,只能编组命令的无环图。
字符串类型编码
字符串字段可以为 null。如果它为 null,则它会编码为单个“0”字节。
字符串编码
[=If not-null is 1===========]
+----------+ [ +-------+----------------+ ]
| not-null | [ | size | encoded-string | ]
+----------+ [ +-------+----------------+ ]
| byte | [ | short | size octects | ]
+----------+ [ +-------+----------------+ ]
[============================]
字段 | 描述 |
---|---|
非 null | 如果字符串不为 null,则为 1,如果字符串为 null,则为 0 |
大小 | UTF-8 编码字符串的字节数 |
编码字符串 | 字符串的 UTF-8 编码形式 |
字节数组类型编码
字节数组字段可以为 null。如果它为 null,则它会编码为单个“0”字节。
字节数组编码
[=If not-null is 1========]
+----------+ [ +------+--------------+ ]
| not-null | [ | size | data | ]
+----------+ [ +------+--------------+ ]
| byte | [ | int | size octects | ]
+----------+ [ +------+--------------+ ]
[=========================]
字段|描述 —|— 非 null|如果字节数组不为 null,则为 1,如果为 null,则为 0 大小|字节数组中的字节数 数据|字节数组的数据
N 个大小的字节数组类型编码
固定大小的字节数组字段不能为 null,并且其长度必须为 N 长度。用于始终为固定大小的字节数组。
N 个大小的字节数组编码
+-----------+
| data |
+-----------+
| N octects |
+-----------+
字段|描述 —|— 数据|字节数组的数据
Throwable 类型编码
Throwable 字段可以为 null。如果它为 null,则它会编码为单个“0”字节。
throwable 编码
[=If not-null is 1===========================================================================]
[ [=If StackTraceEnabled option is enabled.==================] ]
[ [ [=Repeated size times======================] ] ]
+----------+ [ +----------------+---------+ [ +-------+ [ +--------+--------+--------+-------------+ ] ] ]
| not-null | [ | exception-name | message | [ | size | [ | class | method | file | line-number | ] ] ]
+----------+ [ +----------------+---------+ [ +-------+ [ +--------+--------+--------+-------------+ ] ] ]
| byte | [ | string | string | [ | short | [ | string | string | string | int | ] ] ]
+----------+ [ +----------------+---------+ [ +-------+ [ +--------+--------+--------+-------------+ ] ] ]
[ [ [============================================] ] ]
[ [==========================================================] ]
[============================================================================================]
字段 | 描述 |
---|---|
非 null | 如果 Throwable 不为 null,则为 1,如果 Throwable 为 null,则为 0 |
异常名称 | 异常的类名 |
消息 | 异常消息 |
大小 | 堆栈跟踪中的堆栈帧数 |
类 | 堆栈帧中类的名称 |
方法 | 堆栈帧中方法的名称 |
文件 | 堆栈帧中文件的名称 |
行号 | 堆栈帧中的行号 |
如果在交换了 WIREFORMAT_INFO 数据包之后启用了 StackTraceEnabled 编码选项,则每个 Throwable 字段都会附加堆栈跟踪数据。
嵌套命令类型编码
嵌套命令字段可以为 null。如果它为 null,则它会编码为单个“0”字节。
嵌套对象编码
[=If not-null is 1===================]
+----------+ [ +------+-------------------------+ ]
| not-null | [ | type | command-specific-fields | ]
+----------+ [ +------+-------------------------+ ]
| byte | [ | byte | variable sized | ]
+----------+ [ +------+-------------------------+ ]
[====================================]
字段 | 描述 |
---|---|
非 null | 如果 Throwable 不为 null,则为 1,如果 Throwable 为 null,则为 0 |
类型 | 命令类型标识符 |
特定于命令的字段 | 命令的数据。它的编码取决于使用的类型 |
缓存的嵌套命令类型编码
嵌套命令类型可以被缓存,以便对同一对象的后续编组操作会产生更小的在线大小。默认情况下,CacheEnabled 选项未启用,因此使用标准的嵌套对象编码。
缓存对象编码
[=If CacheEnabled option is enabled=====================]
[ [=If new-value is 1===========] ]
[ +-----------+-------+ [ +-------------------------+ ] ]
[ | new-value | key | [ | command-specific-fields | ] ]
[ +-----------+-------+ [ +-------------------------+ ] ]
[ | byte | short | [ | nested-object | ] ]
[ +-----------+-------+ [ +-------------------------+ ] ]
[ [=============================] ]
[=====================================================] ]
[=If CacheEnabled option is disabled =]
[ +-------------------------+ ]
[ | command-specific-fields | ]
[ +-------------------------+ ]
[ | nested-object | ]
[ +-------------------------+ ]
[=====================================]
字段 | 描述 |
---|---|
新值 | 如果值不在缓存中,则为 1,如果已在缓存中,则为 0 |
键 | 用于在缓存中标识值的键 |
特定于命令的字段 | 命令的数据。它的编码取决于使用的类型 |
松散编码
迄今为止解释的默认编码称为“松散编码”,是 OpenWire 首次初始化时使用的默认编码。松散编码易于实现,不会给编组/解组过程增加太多 CPU 开销。它能够在对象树的单次遍历中编组对象图。
紧凑编码
OpenWire 支持另一种编码选项,称为 TightEncoding。使用紧凑编码时,它使用位流来编组所有布尔值,这些布尔值在松散编码中会占用一个字节,而在位流中则占用一个位。为了构建位流,会对对象图进行两次遍历,因此这是一个更密集的 CPU 编组过程,但它会产生更小的在线大小。