RabbitMQ 3.0 搞砸了一些东西
RabbitMQ 包含许多很棒的新功能。但为了实现其中的一些功能,我们需要改变一些东西。所以在这篇博文中,我将列出其中一些内容,以防您需要对它们进行任何操作。
RabbitMQ 包含许多很棒的新功能。但为了实现其中的一些功能,我们需要改变一些东西。所以在这篇博文中,我将列出其中一些内容,以防您需要对它们进行任何操作。
你在 RabbitMQ 中有一个队列。有一些客户端正在从该队列消费。如果你根本不设置 QoS 设置(basic.qos),那么 RabbitMQ 会尽可能快地将队列中的所有消息推送到客户端,只要网络和客户端允许。消费者将在内存中膨胀,因为它们会在自己的 RAM 中缓冲所有消息。如果你询问 RabbitMQ,队列可能看起来是空的,但可能有数百万条消息未被确认,因为它们位于客户端中,随时准备被客户端应用程序处理。如果你添加一个新的消费者,队列中就没有消息可以发送给新消费者了。消息只是被现有客户端缓冲,并且可能需要很长时间才能被处理,即使有其他消费者变得可用,可以更快地处理这些消息。这很不理想。
因此,默认的 QoS prefetch 设置为客户端提供了一个无限缓冲区,这可能导致行为和性能不佳。但是,QoS prefetch 缓冲区大小应该设置为多少?目标是让消费者保持饱和工作,但要最小化客户端的缓冲区大小,以便更多消息保留在 RabbitMQ 的队列中,从而可供新消费者使用,或者在消费者空闲时发送给它们。
我们在 RabbitMQ 总部面临的一个问题是,虽然我们对消息代理的工作原理了如指掌,但我们并没有太多关于设计使用 RabbitMQ 并需要长期可靠、无人值守运行的应用程序的经验。我们花了很多时间在邮件列表中回答问题,也会在这里那里做一些咨询工作,但在某些情况下,是用户构建的应用程序促使我们真正思考 RabbitMQ 的长期行为。最近,我们被要求深入思考队列的基本性能,这让我们对 Rabbit 的配置有了新的认识。
最近,我们推出了Cloud Foundry 的 RabbitMQ 服务,让您可以在 Cloud Foundry 上轻松地启动消息代理以供您的应用程序使用。网上有关于将其与 Ruby on Rails 和使用 Spring 的 Java 应用程序的教程。在这里,我们将探讨如何将 RabbitMQ 服务与 Node.JS 应用程序结合使用。
注意:这篇博文讨论的是为 RabbitMQ 2.5.0 发布的一个 federation 插件预览版。如果您使用的是 2.6.0 或更高版本,federation 是主发行版的一部分;您可以像获取任何其他插件一样获取它。
又一天,又一款新插件发布😃今天发布的是 **federation**。如果您想跳过这篇博文直接下载插件,请前往此处。详细说明请参见此处。
Federation 的高级目标是在广域网和管理域中扩展发布/订阅消息。
为此,我们引入了 **federation exchange** 的概念。federation exchange 像一个给定类型的普通 exchange 一样工作(它可以模拟任何已安装的 exchange 类型的路由逻辑),但它也知道如何连接到 **上游** exchange(这些上游 exchange 本身也可能是 federation exchange)。
RabbitMQ 2.3.1 引入了几个新的插件机制,让您可以更全面地控制用户如何向 Rabbit 进行身份验证,以及我们如何确定他们被授权执行哪些操作。这里有三个问题值得关注:
对于 AMQP,第一个问题通过 SASL 来解答——这是一个嵌入在 AMQP(以及其他各种协议)中的可插拔身份验证机制的简单协议。SASL 允许客户端和服务器协商并使用身份验证机制,而无需“外部”协议了解身份验证的工作细节。
SASL 提供了许多“机制”。从一开始,RabbitMQ 就支持 PLAIN 机制,它基本上是在传输过程中以明文形式发送用户名和密码(当然,整个连接可能由 SSL 保护)。它也支持 AMQPLAIN 机制(概念上与 PLAIN 相同,但如果您有一个 AMQP 编解码器,实现起来会更容易)。RabbitMQ 2.3.1 添加了一个插件系统,允许您添加或配置更多机制,我们编写了一个实现 SASL EXTERNAL 机制的示例插件。
对于那些暂时离开互联网的朋友来说,node.js 是一个基于 Google V8 的事件驱动 JavaScript 引擎。因为它本质上是一个巨大而高效的事件循环,所以它非常适合那些在状态很少的情况下,前后频繁地移动数据的程序。而且它编程起来很有趣,这似乎是很多人共享的观点,因为围绕它已经涌现出大量的库。
这些库中最令人印象深刻的是 Socket.IO。你可以将 Socket.IO 与 node.js 内置的 Web 服务器结合起来,创建一个 WebSocket 服务器,并为浏览器提供一个套接字抽象,在没有 WebSocket 的情况下会退降到 XHR 技巧。(我很高兴能相信 node.js 和 Socket.IO 是由一个仁慈且富有远见的先驱种族为我们创造的;但当然,它们是由勤奋聪明的人创造的。谢谢你们!)
一旦在浏览器中拥有了套接字抽象,一个全新的世界就此打开。具体来说,就我们而言,这是一个全新的消息传递世界。由于 node.js 有一个 AMQP 客户端,我们可以轻松地将其与 RabbitMQ 连接起来;不仅可以连接到其他协议和后端系统,还可以提供浏览器之间、应用程序服务器之间等等的消息传递。
继我们与 ZeroMQ 的 Martin Sustrik 合作的 工作 之后,我决定为浏览器套接字创建一个非常简单的协议,该协议反映了 ZeroMQ (以及因此的 RMQ-0MQ) 中使用的消息传递模式——发布/订阅、请求/应答 和 推/拉 (或管道)。我编写了一个 node.js 库,该库使用 RabbitMQ 来实现消息模式,利用其路由和缓冲功能;由于 RabbitMQ 拥有大量协议适配器和各种语言的客户端,因此桥接功能也随之而来。
消息传递模式的简要说明
发布/订阅 适用于已发布的消息需要传递给多个订阅者的情况。在一般情况下,可以使用各种路由方式来过滤每位订阅者的消息。例如,这可以用于将后端系统的通知广播给用户的浏览器。
请求/应答 用于通过消息传递进行 RPC;请求会以轮询方式分发给工作进程,应答会路由回请求的套接字。这可以由浏览器用来查询后端服务;或者甚至由浏览器互相查询。
管道 用于将进程链接在一起。消息会以轮询方式推送到工作进程,这些工作进程本身可以将消息推送到下一个处理阶段。这可以用于协调用户(或个人)集合之间的工作流程。
在不必要的客套话之后,这里是 rabbit.js。
它只需要一个基本的 RabbitMQ 和 node.js 安装;以及 node-amqp 和 Socket.IO 库。安装说明和这些库的位置在 README 中。(请注意,您需要 我 fork 的 node-amqp。)
它还包含一个微型消息套接字服务器;也就是说,一个接受套接字连接并使用带长度前缀的消息进行通信的 node.js 服务器。由于所有通信都通过 RabbitMQ 进行,您可以通过套接字与连接了 Socket.IO 的浏览器进行通信。您还可以使用 node.js 本身代码中的进程内管道服务器。
总而言之,我很惊讶地发现,只需寥寥几行代码和一些各有所长的技术——node.js 用于有趣的服务器端网络编程,Socket.IO 用于神奇的浏览器套接字,以及 RabbitMQ 用于无忧无虑的消息传递——我就能完成这么多工作。
我正在设置我那台从室友那里“收回”的旧 MacBook,以便能够用于编程。