【问题标题】:RabbitMQ: Bi-directional federated brokers, how do you make all queues pop the message?RabbitMQ:双向联合代理,如何让所有队列弹出消息?
【发布时间】:2016-02-10 18:05:25
【问题描述】:

我有两个使用联合插件配置的代理[1]。两者都指向对方作为上游。

我的测试是:

  • 在代理 A 上发布消息
  • 在代理 B 上消费

结果是:

  • 在代理 B 上消费工作
  • broker B 上的队列弹出消息
  • broker A 上的队列还有消息
    • 我看到的问题是:如果我总是在一个代理上发布,然后总是在另一个代理上消费 --> 那么发布代理上的队列将增长直到它满了并开始丢弃消息.

我想要的结果是:

  • 当消费者在代理 B 上消费时,代理 A 和 B 上的两个队列都会弹出消息

当消费者在代理 B 上消费消息时,如何配置 RabbitMQ 以从所有队列中弹出消息?现在我正在尝试使用 RabbitMQ 联合插件。


[1] 两个代理相互指向上游,我将它们配置为same way as described in the "simple example" given by the documentation,除了有两个代理各自指向对方作为上游。 code for the publisher looks like this 和 code for the consumer looks like this。

【问题讨论】:

  • 我想您使用的是队列联合对吧?并且您想使用来自一个代理的消息,并且另一个代理必须对齐,对吗?
  • @Gabriele re - “[are] you using queue federation?”:我正在使用来自联合“入门”部分的"simple example"。我认为这个“简单示例”使用了联合交易所。 (我的 RabbitMQ 也是 3.1.5 版,没有联合队列 (Federated Queues are available for versions 3.2 and onward)。
  • @Gabriele 你是说联合队列可能是解决问题的方法吗? (我问是因为我注意到您更有经验(我已经购买的 RabbitMQ Cookbook 的作者))。 |||从十分钟 reading about federated queues 开始,听起来他们会完全按照我的需要/想要做(即不同代理上的消费者将从联合队列中消费,这将导致消息在上游队列上消费)。你觉得我的解释对吗?
  • 您是否考虑过使用集群功能而不是联邦?
  • 我使用联合而不是集群,因为联合适用于 WANPHY 或不可靠的链接。

标签: python rabbitmq messagebroker rabbitmq-federation


【解决方案1】:

我创建了这个环境:

服务器 A,服务器 B。

以这种方式创建了一个双向联邦:

联合上游:Server_B = amqp://servera

联合上游:Server_A = amqp://serverb

然后在两台服务器上创建相同的策略:

Pattern : ^fed\.
Apply to: all   
federation-upstream-set:all

为服务器 A 创建了一个名为:fed.test1 的队列,然后为服务器 B 创建了一个消费者:

 ConnectionFactory factory = new ConnectionFactory();
 factory.setHost("localhost");
 factory.setPort(5673);
 Connection connection = factory.newConnection();
 Channel channel = connection.createChannel();


Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                        throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Message   '" + message );
                }
            };
channel.basicConsume("fed.test1",  true, consumer);

然后向Server A发布消息--->fed.test1

消息已被服务器 B 消费,并且两个队列(服务器 A、服务器 B)的队列消息计数为 zero。

这如你所料。

希望对您有所帮助。

【讨论】:

  • 请注意,这不会在联合中维护单个逻辑队列。只有当有消费者处理消息时,服务器 A 上的消息才会发送到服务器 B。换句话说,这不会在每个服务器上创建消息的冗余实例。 Exchange federation 是另一种选择,它将简单地将消息复制到下游服务器,在每台服务器上留下两条独立但相同的可消费消息。似乎没有一个选项可以保留邮件副本并确保单次传递。
【解决方案2】:

@Trevor Boyd Smith,您可以考虑如下所示的选项 2 或 3。

选项 1:双向联合交换

一条消息最终会出现在代理 A 和 B 中,每个代理一个副本,彼此独立。换句话说,例如,即使在代理 B 已将消息传递给其消费者之后,该消息的另一个副本仍保留在代理 A 中。

优势:您将始终拥有两份消息副本,每个代理一份,这是高度可用的。

缺点:您需要有一个消费者连接到每个代理。

选项 2:双向联合队列

一条消息将在两个代理中的一个中结束。默认情况下,已经发布消息的broker会优先将消息入队;但是,如果只有其他代理有消费者,则消息将移动到其他代理。

消息最终到达哪个代理无关紧要,消息只会由连接到任一代理的消费者一次且一次地传递。

优点:消息将一次且仅一次传递给连接到任一代理的消费者。

缺点:邮件只会有一份副本。如果得到消息的broker宕机了,其他broker就无法获取消息了。但是,如果您对最终的一致性感到满意,那么这个选项就可以了。原因是当有问题的代理恢复运行时,消息最终将可用。

选项 3:双向联合交换和队列

在这种情况下,一条消息将在两个代理中结束,每个代理一个副本。相同的消息将被传递给连接到任一代理的消费者,两次!一旦消息被传递两次,它将在两个代理中消失。 (如果有两个消费者,一个连接到每个代理,每个代理将向其消费者传递一次相同的消息。)

优点:消费者可以连接到任一broker,每个broker中的消息都会被投递和出队。

缺点:同一条消息会被发送两次。解决方法是,在处理消息之前,检查是否已经处理了相同的消息。

注意:

这并不意味着哪个选项比其他选项更好。这完全取决于您的用例,还有许多其他配置可以发挥作用,这可能会改变行为。

【讨论】:

    猜你喜欢
    • 2015-12-17
    • 2013-12-18
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    相关资源
    最近更新 更多