AMQP 1.0 通过 WebSocket
我们很高兴地宣布 VMware Tanzu RabbitMQ 4.1 中对 AMQP 1.0 over WebSocket 的支持。
此功能使任何基于浏览器的应用程序都可以使用 AMQP 1.0 与 RabbitMQ 通信,为各种高效的基于浏览器的业务消息传递场景铺平了道路。
什么是 WebSocket?
WebSocket 在 RFC 6455 中定义,是一个由两部分组成的简单协议
Client Server
| |
|================ Part I =================|
|---- WebSocket Handshake Request ------->|
| GET /some/path HTTP/1.1 |
| Upgrade: websocket |
| Connection: Upgrade |
| Sec-WebSocket-Protocol: amqp |
| |
|<-- WebSocket Handshake Response --------|
| HTTP/1.1 101 Switching Protocols |
| Upgrade: websocket |
| Connection: Upgrade |
| Sec-WebSocket-Protocol: amqp |
| |
|================ Part II ================|
|<========= WebSocket Connection ========>|
| Full-duplex communication |
| |
|<---------- Binary Data [AMQP] --------->|
|<---------- Binary Data [AMQP] --------->|
|<---------- Binary Data [AMQP] --------->|
| ... |
| |
|----------- Close Frame ---------------->|
|<---------- Close Frame -----------------|
第一部分是握手,包括 HTTP 请求和响应。第二部分是数据传输:客户端和服务器之间保持打开单个 TCP 连接,允许任何一方随时将二进制数据推送到另一方。
在此示例中,二进制数据由 AMQP 帧 组成,因为客户端向服务器提议 Sec-WebSocket-Protocol: amqp
,并且服务器接受了它。Sec-WebSocket-Protocol
标头指定了分层在 WebSocket 之上的应用层协议。
此通信的协议栈如下所示
+-------------------+
| AMQP | Application Layer
+-------------------+
| WebSocket |
+-------------------+
| TCP | Transport Layer
+-------------------+
| IP | Network Layer
+-------------------+
| Ethernet | Link Layer
+-------------------+
WebSocket 协议本身并不规定应用层协议,从而提供了灵活性。它可以支持任何协议,包括 STOMP 和 MQTT。
为什么选择 WebSocket?
WebSocket 提供了以下优势
- 浏览器兼容性: 它允许基于浏览器的应用程序使用 HTTP 以外的应用层协议。出于安全原因,浏览器限制 JavaScript 打开原始 TCP 连接以使用 AMQP 或 MQTT 等协议进行通信。WebSocket 可防止在浏览器中运行的恶意 JavaScript,从而通过 WebSocket 层实现安全的应用层通信。
- 防火墙穿越: WebSocket 促进了在具有限制性防火墙规则的环境中的通信。例如,虽然可能允许端口 443 (
https
),但端口 5671 (amqps
) 可能会被阻止。在这种情况下,可以使用端口 443 上的安全 WebSocket (wss
) 连接来通信 AMQP。
现代浏览器普遍支持 WebSocket,使其成为基于 Web 的应用程序的实用选择。
RabbitMQ 中的 WebSocket
长期以来,RabbitMQ 通过 rabbitmq_web_stomp
和 rabbitmq_web_mqtt
插件分别支持 STOMP over WebSocket 和 MQTT over WebSocket。
VMware Tanzu RabbitMQ 4.1 引入了新的 rabbitmq_web_amqp
插件,该插件符合 AMQP WebSocket Binding Committee Specification 01。此插件的运行方式与现有的 WebSocket 插件类似,启动一个监听器来管理 WebSocket 协议方面。
以前,基于浏览器的应用程序使用 MQTT 或 STOMP over WebSocket 连接到 RabbitMQ,通常是由于缺乏 AMQP 支持。AMQP over WebSocket 带来了以下好处
- 功能丰富性: 与为简单性而设计的 MQTT 和 STOMP 不同,AMQP 是一种为业务消息传递而设计的协议,支持更高级的功能。
- 效率:AMQP 是二进制且高效的,而 STOMP 是面向文本的。
这使得 AMQP over WebSocket 成为高效、功能丰富的基于浏览器的业务消息传递的绝佳选择。
WebSocket 中继
在此插件之前,一种解决方法是使用 WebSocket 中继。中继将接受来自客户端的 WebSocket 连接,并打开与 RabbitMQ 的单独 TCP 连接。虽然功能齐全,但这种方法引入了诸如以下缺点:
- 来自额外网络跳跃的额外延迟。
- 增加资源使用量以维持每个客户端两个 TCP 连接。
- 部署和监控中继的操作开销。
- 另一个潜在的故障点。
新插件通过提供直接的 AMQP over WebSocket 支持消除了这些问题。
示例
RabbitMQ 包含插件 rabbitmq_web_stomp_examples
和 rabbitmq_web_mqtt_examples
,其中包含名为 “echo” 和 “bunny” 的基本示例。同样,VMware Tanzu RabbitMQ 4.1 引入了 rabbitmq_web_amqp_examples
。
AMQP over WebSocket “bunny” 示例的工作方式如下
rabbitmq_web_amqp_examples
插件创建一个名为amq.web_amqp_examples.bunny
的 流。- 当访问
http://localhost:15670/web-amqp-examples/bunny.html
时,该插件提供文件bunny.html
、bunny.png
和rhea.js
。bunny.html
文件显示bunny.png
。此外,bunny.html
文件包含 JavaScript 代码,该代码创建从浏览器到 RabbitMQ 的 AMQP over WebSocket 连接
// default AMQP over WebSocket port and path in RabbitMQ
var url = "ws://" + location.hostname + ":15678/ws"
var ws = client.websocket_connect(WebSocket);
var connection = client.connect({
"connection_details":ws(url, ["amqp"]),
// Setting username without password causes rhea to use SASL mechanism ANONYMOUS.
"username": "ignored",
});
此代码片段使用 rhea.js
文件。rhea 是一个开源 AMQP 1.0 TypeScript/JavaScript 库。可以通过在 rhea
存储库的根目录中运行以下命令来创建此单个文件
npm install
make browserify
浏览器不仅打开了 AMQP over WebSocket 连接,还创建了 会话 以及与 预先声明的流 的链接
var address = "/queues/" + stream
client.on("connection_open", function (context) {
sender = context.connection.open_sender(address);
// If we open a new brower tab, we want to see the existing drawing.
const filter = {'my-filter': amqp_types.wrap_described("first", "rabbitmq:stream-offset-spec")};
context.connection.open_receiver({source:{address: address, filter: filter}});
});

- 如果您在同一 URL 打开第二个浏览器选项卡,它也会创建一个 AMQP over WebSocket 连接,发布到和消费来自同一流。
- 当您在两个浏览器选项卡中的任何一个上绘图时,另一个选项卡会看到实时绘图,因为两个选项卡都从同一流中消费

客户端
截至 RabbitMQ 4.1,以下 RabbitMQ AMQP 1.0 客户端库 可用
- RabbitMQ AMQP 1.0 Java 客户端
- RabbitMQ AMQP 1.0 .NET 客户端
- RabbitMQ AMQP 1.0 Go 客户端
- RabbitMQ AMQP 1.0 Python 客户端
其中一些库尚处于早期阶段。
新的 AMQP over WebSocket 插件的全部优势将在 RabbitMQ AMQP 1.0 JavaScript 库中实现,因为正如 Native AMQP 1.0 博客文章中所解释的那样,这些 RabbitMQ 特定的包装器允许声明 交换机、队列 和 绑定。
由于截至 RabbitMQ 4.1 尚无此类 RabbitMQ 特定的 JavaScript 库可用,因此目前可以使用现有的 JavaScript AMQP 1.0 客户端(例如 rhea)代替。
总结
VMware Tanzu RabbitMQ 4.1 使浏览器能够使用 AMQP 1.0 与 RabbitMQ 通信。
请注意:新的 AMQP over WebSocket 插件是一个闭源功能,仅在商业 VMware Tanzu RabbitMQ 产品中提供。它不是开源 RabbitMQ 发行版的一部分。
虽然这篇博文用一个有趣的兔子示例说明了该功能,但 AMQP 1.0 是一种为业务消息传递构建的高效协议。想想企业工具,如 Salesforce、Workday 或 Jira - 所有这些工具都在浏览器中运行并受益于实时消息传递。