您如何使用 RabbitMQ java 客户端库处理从错误连接中恢复的问题?

2022-09-04 02:51:03

我很想知道其他人如何使用官方的RabbitMQ java客户端库处理从错误连接中恢复的问题。我们正在使用它将应用程序服务器连接到我们的RabbitMQ集群,并且我们已经实现了几种不同的方法来从连接故障中恢复,但没有一种感觉完全正确。

想象一下这个伪应用程序:

public class OurClassThatStartsConsumers {
    Connection conn;

    public void start() {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUsername("someusername");
        factory.setPassword("somepassword");
        factory.setHost("somehost");
        conn = factory.newConnection();

        new Thread(new Consumer(conn.createChannel())).start();
    }
  }

class Consumer1 implements Runnable {
    public Consumer1(Channel channel) {
         this.channel = channel;
    }

    @Override
    public void run() {
        while (true) {
             ... consume incoming messages on the channel...
            // How do we handle that the connection dies?
        }
    }
}

在现实世界中,我们有数百名消费者。那么,如果连接中断会发生什么呢?在上面的示例 Consumer1 中,当连接关闭时,通道也会关闭,这是一种我们无法恢复的状态。因此,让我们看一些解决此问题的方法:

解决方案 A)

让每个使用者都有自己的连接,并注册在连接失效时触发的事件,然后处理重新连接。

优点:它的工作原理

缺点:

  • 由于我们有很多消费者,我们可能不希望那么多连接。
  • 我们可能有很多重复的代码用于重新连接到兔子并处理重新连接

解决方案 B)

让每个使用者使用相同的连接并订阅其连接失败事件。

优点:连接数比解决方案 A 中的连接数少

缺点:由于连接已关闭,我们需要重新打开/替换它。Java客户端库似乎没有提供重新打开连接的方法,因此我们必须用新连接替换它,然后以某种方式通知所有消费者这个新连接,他们将不得不重新创建通道和消费者。再一次,我不想在消费者身上看到很多逻辑最终都在那里。

解决方案 C)

Wrap 和类是处理重新连接逻辑的类,使用者只需要知道类。在连接失败时,将处理重新建立连接,一旦连接,将自动创建新的通道并注册消费者。ConnectionChannelWrappedChannelWrappedConnectionWrappedConnection

优点:它有效 - 这实际上是我们今天使用的解决方案。

缺点:这感觉就像一个黑客,我认为这是底层库应该更优雅地处理的事情。

也许有更好的方法?API文档没有那么多关于从错误连接中恢复的内容。任何输入都受到赞赏:)


答案 1

从 3.3.0 版开始,您可以使用自动恢复,这是 Java 客户机的新功能。来自 Java API 指南 (http://www.rabbitmq.com/api-guide.html#recovery)

要启用自动连接恢复,请使用 factory.setAutomaticRecovery(true):


答案 2

在RabbitMQ邮件列表上得到了一些很好的答案,基本上建议了上面列出的解决方案C。

解决方案 C)

Wrap Connection 和 Channel 类是处理重新连接逻辑的类,使用者只需要了解 WrappedChannel 类。在连接失败时,WrappedConnection 会处理重新建立连接,一旦连接,WrappedConnection 将自动创建新的通道并注册使用者。

优点:它有效 - 这实际上是我们今天使用的解决方案。

缺点:这感觉就像一个黑客,我认为这是底层库应该更优雅地处理的事情。

这就是在Java之上构建的两个客户端—— Langohr和Mark Hare——所做的。这不是一个黑客,而是一个必要的解决方法,因为连接恢复目前不是由Java客户端执行的(如果你问我,它应该是一个核心功能)。

所以这是一个可行的方法。

也看看天琴座:https://github.com/jhalterman/lyra

断续器

软件工程师,Pivotal/RabbitMQ

和:

嗨彼得,

解决方案C实际上是相当合理的。如果您尝试防止网络故障或群集分区,则使用到同一服务器的多个连接不会获得太多好处。如果一个连接死亡,它们都可能死亡。包装和恢复连接/通道工作正常,正如Michael所提到的,您也可以查看Lyra,因为它可以处理为您恢复资源所涉及的各种角落案例。

干杯,乔纳森

在此处阅读完整主题:

http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2013-October/031564.html

http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2013-November/031573.html


推荐