Publisher Confirms 介绍
在许多消息传递场景中,您不能丢失消息。 由于 AMQP 在消息持久化/处理方面提供的保证很少,因此传统的实现方式是使用 事务,但这可能会慢得无法接受。 为了解决这个问题,我们引入了一个 AMQP 的扩展,即轻量级 Publisher Confirms。
在许多消息传递场景中,您不能丢失消息。 由于 AMQP 在消息持久化/处理方面提供的保证很少,因此传统的实现方式是使用 事务,但这可能会慢得无法接受。 为了解决这个问题,我们引入了一个 AMQP 的扩展,即轻量级 Publisher Confirms。
RabbitMQ 2.3.1 引入了几个新的插件机制,让您可以更全面地控制用户如何向 Rabbit 进行身份验证,以及我们如何确定他们被授权执行哪些操作。这里有三个问题值得关注:
对于 AMQP,第一个问题通过 SASL 来解答——这是一个嵌入在 AMQP(以及其他各种协议)中的可插拔身份验证机制的简单协议。SASL 允许客户端和服务器协商并使用身份验证机制,而无需“外部”协议了解身份验证的工作细节。
SASL 提供了许多“机制”。从一开始,RabbitMQ 就支持 PLAIN 机制,它基本上是在传输过程中以明文形式发送用户名和密码(当然,整个连接可能由 SSL 保护)。它也支持 AMQPLAIN 机制(概念上与 PLAIN 相同,但如果您有一个 AMQP 编解码器,实现起来会更容易)。RabbitMQ 2.3.1 添加了一个插件系统,允许您添加或配置更多机制,我们编写了一个实现 SASL EXTERNAL 机制的示例插件。
不时地,在我们的 邮件列表 和其他地方,都会有人提出在 RabbitMQ 中使用不同的后备存储的想法。后备存储负责将消息写入磁盘(消息可能因为多种原因被写入磁盘),并且经常有人建议看看如果 RabbitMQ 的后备存储被替换为其他存储系统会是什么样子。
这样的改变将允许实现目前不可能的功能,例如带外队列浏览或分布式存储,但消息队列(如 RabbitMQ)的数据存储和访问模式与通用数据库之间存在根本性的差异。事实上,RabbitMQ 故意不将消息存储在这样的数据库中。
我很高兴地宣布 AMQP 0.7 发布了,正如我在上一篇博文中承诺的那样。那么,有什么变化呢?
在过去一年里,AMQP gem 的开发几乎停滞不前,因为它的最初作者 Aman Gupta(@tmm1)非常忙碌。许多 bug 未得到解决,代码变得陈旧过时,也没有添加新功能或文档。
这时,我开始与 RabbitMQ 的人讨论合作的可能性。事实上,最初我联系 VMware 是因为看到 Ezra Zygmuntowicz 在为他的云团队招人,但当我发现 VMware 最近收购了伦敦的 RabbitMQ 项目时,我产生了兴趣。我签署了合同,从 script/console 切换到 Wireshark 和 RabbitMQ Tracer,从 11 月份开始,我一直在愉快地开发 AMQP 和 AMQ-Protocol gems。
我们一如既往地在对一项新协议的支持进行原型设计。这项新协议名为“AMQP 1.0 R0”,它是 AMQP 工作组(RabbitMQ,以及后来的 VMware,都是其成员)提出的新版本。“R0”表示它是修订版建议的第一个版本。该规范尚不完整:有许多待办事项(TODO),并且在很大程度上尚未经过验证。这两个事实也是促使我们进行原型设计的因素之一。
原型代码已在 github 上镜像:http://github.com/rabbitmq/rabbitmq-amqp1.0。它的构建方式与我们所有的插件完全相同。
AMQP 1.0 R0 规范与之前版本的 AMQP 规范不同之处在于,它不定义 broker 模型;也就是说,它不定义 exchange、queue 和 binding,或者它们的等价物。该协议实际上只关乎将消息从一个代理传输到另一个代理,然后就结果达成一致。这意味着它可以附加到消息 broker 实现上,以及其他用途——其理念是人们可以调整现有模型以适应需求。
在我们的案例中,现有的模型是 AMQP 0-9-1 的模型,并包含一些泛化和扩展(例如,链式 binding)。因此,我们原型设计的目标是能够同时使用 1.0 客户端和 0-9-1 客户端连接并完成一些有用的工作。
好消息是,我们已经实现了这一点。实际上,该插件可以配置为替代 Rabbit 原有的网络监听器,并能够愉快地与 AMQP 0-8、0-9-1 和 1.0 客户端进行通信。在此过程中,我们确实进行了一些创新,并且有一些规范的部分是我们没有实现的。这些内容稍后将在 README 文件中详细说明。
其中一项重要的创新是填补规范中未定义的部分。其中一些细节已在我们为 AMQP 工作组所做的客户端-broker 协议工作中有所说明。我们希望原型设计能帮助进一步完善这部分内容。
下周,我将把我们的原型带到AMQP 1.0 “Connectathon”,届时它将与其他核心协议的实现(并非所有实现都是开源的)进行测试。同样,这将有助于消除规范中互操作性方面的障碍。
RabbitMQ 需要更多、更好的文档。(谁不需要呢?)特别是,我们需要更多、更好的入门材料,向读者介绍各种基本概念,解释它们为什么重要,并激励他们继续阅读并了解更多关于 RabbitMQ 的信息。这是那篇介绍的第一章。欢迎您提出意见,第二章和第三章将很快跟进。(您可能已经知道所有这些了,但令人惊讶的是,很多人并不知道。本介绍是为他们准备的。)
对于那些暂时离开互联网的朋友来说,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 用于无忧无虑的消息传递——我就能完成这么多工作。
RabbitMQ 2.1.1 版本带来了对交换机之间绑定的支持。这是 AMQP 规范的扩展,使用此功能将(目前)导致您的应用程序只能与 RabbitMQ 配合使用,而无法与市面上其他众多 AMQP 0-9-1 消息中间件兼容。然而,这项扩展极大地提高了路由拓扑的表达能力和灵活性,并同时解决了一些可伸缩性问题。
常规绑定允许交换机绑定到队列:发布到交换机的消息,只要满足交换机及其绑定的各种条件,就会通过各种绑定,并最终附加到每个绑定末尾的队列中。这对于许多用例来说已经足够了,但灵活性非常有限:它总是只有一步——消息被发布到一个交换机,具有一套绑定,因此只有一套可能的目的地。如果您需要更灵活的方式,则不得不多次发布同一条消息。通过交换机到交换机绑定,一条消息可以经过任意数量的不同类型的交换机,实现比以往任何时候都更复杂的路由拓扑。
最近,我和 Michael Bridgen 实现了一个桥接器,用于将 RabbitMQ 代理与使用 0MQ 进行消息传递的应用程序连接起来。
它在这里: http://github.com/rabbitmq/rmq-0mq
那么:用户同时使用这两个产品能获得什么样的好处?