11

RabbitMQ 和 Python 是否可以进行基于内容的路由?

AMQP 标准和 RabbitMQ 声称支持基于内容的路由,但是是否有任何 Python 库支持指定基于内容的绑定等?

我目前使用的库(py-amqplib http://barryp.org/software/py-amqplib/)似乎只支持简单模式匹配(#、*)的基于主题的路由。

4

2 回答 2

20

答案是“是的”,但还有更多... :)

让我们首先就基于内容的路由的含义达成一致。有两种可能的意思。有人说它是基于消息的标题部分。其他人说它是基于消息的数据部分。

如果我们采用第一个定义,这些或多或少是我们所做的假设:数据存在于某个地方,并通过某个软件发送到 AMQP 代理。我们假设该软件对数据有足够的了解,可以将键值 (KV) 对放在描述内容的消息的标头中。理想情况下,发送者也是数据的生产者,因此它拥有我们想要的尽可能多的信息。假设数据是图像。然后我们可以让发送方将 KV 对放在消息头中,如下所示:

width=1024
height=768
mode=bw
photographer=John Doe

现在我们可以通过创建适当的队列来实现基于内容的路由。假设我们对黑白图像执行单独的操作,对彩色图像执行单独的操作。我们可以创建两个队列,一个用 接收消息,mode=bw另一个用接收消息mode=colour。然后我们有单独的客户端监听这些队列。代理执行路由,我们的客户端中没有任何东西需要知道路由。

如果我们采用第二个定义,我们会从不同的假设出发。我们假设数据存在于某个地方,并通过某个软件发送到 AMQP 代理。但我们认为要求该软件使用 KV 对填充标头是不明智的。相反,我们希望根据数据本身做出路由决策。

在 AMQP 中有两种选择:您可以决定为您的特定数据格式实现新的交换,或者您可以将路由委托给客户端。

在 RabbitMQ 中,有 direct(1-to-1)、fanout(1-to-N)、headers(header-filtered 1-to-N)和 topic(topic-filtered 1-to-N)交换,但你可以根据AMQP标准实现自己的。这需要阅读大量 RabbitMQ 文档并在 Erlang 中实现交换。

另一种选择是在 Python 中创建一个 AMQP 客户端,以侦听特殊的“内容路由队列”。每当消息到达队列时,您的路由器客户端就会将其拾取,做任何需要做出路由决定的事情,然后将消息发送回代理到合适的队列。因此,为了实现上述场景,您的 Python 程序将检测图像是黑白还是彩色,并将(重新)发送到“黑白”或“彩色”队列,其中一些合适的客户将接管。

因此,关于您的第二个问题,您在客户端中实际上没有做任何基于内容的绑定。您的客户端可以如上所述工作,或者您在 RabbitMQ 本身中创建新的交换类型。然后,在您的客户端设置代码中,您将交换类型定义为您的新类型。

希望这能回答你的问题!

于 2010-08-11T12:41:13.043 回答
6

在 RabbitMQ 中,路由是交换决定将消息放置在哪些队列上的过程。您将所有消息发布到交换器,但您只接收来自队列的消息。这意味着交换是对消息转发或复制做出一些决定的过程的一个积极部分。

RabbitMQ 包含的主题交换会查看传入消息(routing_key)上的字符串,并将其与声明希望从交换接收消息的所有队列提供的模式(binding_keys)匹配。

RabbitMQ 源代码在网上,因此您可以在这里查看主题交换代码:http: //hg.rabbitmq.com/rabbitmq-server/file/9b22dde04c9f/src/rabbit_exchange_type_topic.erl 有很多复杂性处理称为 trie 的数据结构,它允许非常快速的查找。事实上,在 Internet 路由器内部使用了相同的数据结构。

在这里找到的标头交换http://hg.rabbitmq.com/rabbitmq-server/file/9b22dde04c9f/src/rabbit_exchange_type_headers.erl 可能更容易理解。如您所见,进行不同类型的交换不需要很多代码。如果您想检查内容(或者可能只是查看消息的前几个字节,您应该能够快速识别 XML 与 JSON 与其他内容。如果您的 JSON 对象和 XML 文档维护特定的元素序列,那么您应该能够在不解析整个消息体的情况下区分不同的 JSON 对象(或 XML 文档类型)。

于 2011-06-01T04:17:58.637 回答