跳至主内容

WebSocket 上的 AMQP 1.0

·6 分钟阅读

我们很高兴地宣布在 VMware Tanzu RabbitMQ 4.1 中支持 WebSocket 上的 AMQP 1.0。

此功能使任何基于浏览器的应用程序都能够使用 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 具有以下优势:

  1. 浏览器兼容性:它允许基于浏览器的应用程序使用 HTTP 以外的应用层协议。出于安全原因,浏览器限制 JavaScript 打开原始 TCP 连接来使用 AMQP 或 MQTT 等协议。WebSocket 可以防止在浏览器中运行的恶意 JavaScript,从而实现基于 WebSocket 层的安全应用层通信。
  2. 防火墙穿透:WebSocket 有助于在具有限制性防火墙规则的环境中进行通信。例如,虽然端口 443 (https) 可能被允许,但用于 amqps 的端口 5671 可能会被阻止。在这种情况下,可以使用端口 443 上的安全 WebSocket (wss) 连接来通过 AMQP 进行通信。

现代浏览器普遍支持 WebSocket,使其成为基于 Web 的应用程序的实用选择。

RabbitMQ 中的 WebSocket

长期以来,RabbitMQ 分别通过 rabbitmq_web_stomprabbitmq_web_mqtt 插件支持 WebSocket 上的 STOMPWebSocket 上的 MQTT

VMware Tanzu RabbitMQ 4.1 引入了新的 rabbitmq_web_amqp 插件,该插件符合 AMQP WebSocket 绑定委员会规范 01。此插件的运行方式与现有的 WebSocket 插件类似,通过启动侦听器来管理 WebSocket 协议相关的方面。

此前,基于浏览器的应用程序通常由于缺乏 AMQP 支持而使用 WebSocket 上的 MQTT 或 STOMP 连接到 RabbitMQ。WebSocket 上的 AMQP 带来了以下好处:

  • 功能丰富:与旨在追求简洁的 MQTT 和 STOMP 不同,AMQP 是一种专为商业消息传递而设计的协议,支持更多高级功能。
  • 高效:AMQP 是二进制且高效的,而 STOMP 是面向文本的。

这使得 WebSocket 上的 AMQP 成为高效、功能丰富的浏览器端商业消息传递的绝佳选择。

WebSocket 中继

在此插件发布之前,一种变通方法是使用 WebSocket 中继(Relay)。中继会接受来自客户端的 WebSocket 连接,并打开单独的 TCP 连接到 RabbitMQ。虽然可行,但这种方法存在以下弊端:

  1. 额外的网络跳数导致的延迟增加。
  2. 为每个客户端维持两个 TCP 连接导致资源使用量增加。
  3. 部署和监控中继的运维开销。
  4. 潜在的额外故障点。

新插件通过提供直接的 WebSocket 上的 AMQP 支持消除了这些问题。

示例

RabbitMQ 包含了带有名为 “echo” 和 “bunny” 的基础示例的 rabbitmq_web_stomp_examplesrabbitmq_web_mqtt_examples 插件。同样,VMware Tanzu RabbitMQ 4.1 也引入了 rabbitmq_web_amqp_examples

WebSocket 上的 AMQP “bunny” 示例工作流程如下:

  1. rabbitmq_web_amqp_examples 插件创建一个名为 amq.web_amqp_examples.bunny流 (stream)
  2. 当访问 https://:15670/web-amqp-examples/bunny.html 时,插件会提供 bunny.htmlbunny.pngrhea.js 文件。bunny.html 文件显示 bunny.png。此外,bunny.html 文件包含 JavaScript 代码,用于从浏览器创建到 RabbitMQ 的 WebSocket 上的 AMQP 连接。
// 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

浏览器不仅打开了 WebSocket 上的 AMQP 连接,还创建了一个 会话 (session) 以及指向预声明流或从流中引出的 链接 (links)

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}});
});

AMQP over WebSocket connection
WebSocket 上的 AMQP 连接

  1. 如果您在相同的 URL 下打开第二个浏览器标签页,它也会创建一个向同一流发布并从中消费的 WebSocket 上的 AMQP 连接。
  2. 当您在两个浏览器标签页中的任何一个上进行绘画时,另一个标签页会看到实时绘图,因为两个标签页都从同一个流中进行消费。

Bunny Example
Bunny 示例

客户端

作为 rhea 的替代方案,您可以使用 RabbitMQ AMQP 1.0 JavaScript 库。正如在 原生 AMQP 1.0 博客文章中所述,RabbitMQ 库包含 RabbitMQ 特定的功能,例如声明 交换机 (exchanges)队列 (queues)绑定 (bindings)

总结

VMware Tanzu RabbitMQ 4.1 使浏览器能够使用 AMQP 1.0 与 RabbitMQ 进行通信。

请注意:新的 WebSocket 上的 AMQP 插件是一项闭源功能,仅在商业化的 VMware Tanzu RabbitMQ 产品中提供。它不属于开源 RabbitMQ 发行版的一部分。

虽然这篇博客文章通过一个有趣的兔子示例来说明该功能,但 AMQP 1.0 是一种专为商业消息传递而构建的高效协议。想想 Salesforce、Workday 或 Jira 等企业工具——它们都在浏览器中运行,并能从实时消息传递中获益。

© . This site is unofficial and not affiliated with VMware.