<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-tcp-eventbus-bridge</artifactId>
<version>5.2.1</version>
</dependency>
Vert.x TCP EventBus 网桥 (vertx-tcp-eventbus-bridge)
Vert.x TCP EventBus bridge 为外部系统提供了直接基于原生 TCP Socket 与 Vert.x 内部事件总线(Event Bus)进行双向通信的轻量级网桥服务。 要在项目中使用该组件,请在构建描述文件中添加以下依赖:
-
Maven(在
pom.xml中):
-
Gradle(在
build.gradle文件中):
compile 'io.vertx:vertx-tcp-eventbus-bridge:5.2.1'
TCP EventBus 网桥直接构建在原始 TCP 之上。这意味着任何具备建立 TCP Socket 能力的外部应用(无论何种开发语言或运行环境),均可直接同远程 Vert.x 实例的 Event Bus 展开全双工交互。
相较于基于 HTTP WebSocket 的 SockJS 网桥,TCP 网桥的核心优势在于极度轻量与极低资源消耗:完全去除了 HTTP 握手与 WebSocket 协议栈开销,代之以纯粹的原生 TCP 套接字。这在嵌入式 IoT 设备或受限环境中表现极其出色。
即便对于普通应用,该协议也凭借清晰简单的二进制帧结构,为非 JVM 语言生态提供了一条高效可靠的集成纽带。
通信帧协议规范
协议设计力求极致极简,客户端与服务端之间的双向通信均采用统一的数据帧(Frame)封装。数据帧结构如下:
<长度: 32位无符号大端整数><{
type: String,
address: String,
(replyAddress: String)?,
headers: JsonObject,
body: JsonObject
}: JSON对象>
通信内容由一个 JSON 报文构成(压缩或带空白均可)。每个 JSON 报文前必须强制附加一个 32 位大端序(Big-Endian)正整数(4 字节),用以指明后续完整 JSON 报文字符串的准确字节长度。
客户端上送消息支持的 type 类型包括:
-
send:向指定address发送点对点消息 -
publish:向指定address广播发布消息 -
register:订阅监听发往或广播至某address的消息 -
unregister:取消对某address的消息订阅 -
ping:向网桥发送心跳 ping 探活包
请注意:replyAddress 字段为选填项,仅在 send 类型的消息中生效。携带该字段的消息在服务端完成处理后,将收到一条发往该 replyAddress 地址的响应消息。
网桥服务端回推给客户端的消息支持的 type 包括:
-
message:在客户端订阅的address上收到发送或发布的消息 -
err:表示处理出错(错误明细包含在body中) -
pong:对客户端发送的ping心跳探针返回响应
项目源码中附带了一个 Node.js 客户端参考实现。该客户端提供了与 SockJS 网桥一致的高层 API 抽象,便于在 TCP 与 SockJS 实现之间灵活平滑切换。
启动网桥示例
以下是创建并启动 TCP 网桥的基础代码:
TcpEventBusBridge bridge = TcpEventBusBridge.create(
vertx,
new BridgeOptions()
.addInboundPermitted(new PermittedOptions().setAddress("in"))
.addOutboundPermitted(new PermittedOptions().setAddress("out")));
bridge.listen(7000).onComplete(res -> {
if (res.succeeded()) {
// 网桥成功监听在 7000 端口
} else {
// 监听失败!
}
});
监听 Unix 域套接字 (Domain Sockets)
在 JDK 16+ 运行时或启用了 Vert.x 原生网络传输 环境下,TCP 网桥服务端还支持直接监听 Unix 域套接字(Domain Socket)文件,实现本机超高性能 IPC 通信:
SocketAddress domainSocketAddress = SocketAddress.domainSocketAddress("/var/tmp/bridge.sock");
bridge.listen(domainSocketAddress).onComplete(res -> {
if (res.succeeded()) {
// Unix Domain Socket 监听成功
} else {
// 失败!
}
});