跳转到主要内容

AMQP 1.0 通过 WebSocket

·6 分钟阅读

我们很高兴地宣布 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 提供了以下优势

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

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

RabbitMQ 中的 WebSocket

长期以来,RabbitMQ 通过 rabbitmq_web_stomprabbitmq_web_mqtt 插件分别支持 STOMP over WebSocketMQTT 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 连接。虽然功能齐全,但这种方法引入了诸如以下缺点:

  1. 来自额外网络跳跃的额外延迟。
  2. 增加资源使用量以维持每个客户端两个 TCP 连接。
  3. 部署和监控中继的操作开销。
  4. 另一个潜在的故障点。

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

示例

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

AMQP over WebSocket “bunny” 示例的工作方式如下

  1. rabbitmq_web_amqp_examples 插件创建一个名为 amq.web_amqp_examples.bunny
  2. 当访问 http://localhost:15670/web-amqp-examples/bunny.html 时,该插件提供文件 bunny.htmlbunny.pngrhea.jsbunny.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}});
});

AMQP over WebSocket connection
AMQP over WebSocket 连接

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

Bunny Example
Bunny 示例

客户端

截至 RabbitMQ 4.1,以下 RabbitMQ AMQP 1.0 客户端库 可用

  1. RabbitMQ AMQP 1.0 Java 客户端
  2. RabbitMQ AMQP 1.0 .NET 客户端
  3. RabbitMQ AMQP 1.0 Go 客户端
  4. 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 - 所有这些工具都在浏览器中运行并受益于实时消息传递。

© . All rights reserved.