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

Pet*_*erg 14 java amqp rabbitmq

我很想知道其他人如何处理使用官方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?
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在现实世界中,我们有数百名消费者.那么如果连接死了怎么办?在上面的示例中,Consumer1无法恢复,当连接关闭时,Channel也会关闭,这是我们无法恢复的状态.那么让我们看看解决这个问题的一些方法:

解决方案A)

让每个消费者拥有自己的连接,并注册连接死亡时触发的事件,然后处理重新连接.

优点:它的工作原理

缺点:

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

解决方案B)

让每个消费者使用相同的连接并订阅它的连接失败事件.

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

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

解决方案C)

换行ConnectionChannel类是处理重新连接逻辑的类,消费者只需要知道WrappedChannel类.在连接失败时,WrappedConnection将处理重新建立连接,一旦连接,WrappedConnection将自动创建新的频道和注册消费者.

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

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

也许有更好的方法?API文档没有谈到从错误连接中恢复的问题.感谢任何输入:)

Ric*_*dOD 10

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

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


Pet*_*erg 6

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

解决方案C)

Wrap Connection和Channel类是处理重新连接逻辑的类,消费者只需要知道WrappedChannel类.在连接失败时,WrappedConnection处理重新建立连接并且一旦连接WrappedConnection将自动创建新的频道并注册消费者.

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

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

这就是两个客户在Java之上构建的 - Langohr和March Hare - do.这不是一个黑客,而是一个必要的工作因为连接恢复目前不是由Java客户端执行的(如果你问我,它应该是一个核心功能).

所以这是一种可行的方法.

看看Lyra:https://github.com/jhalterman/lyra.

MK

软件工程师,Pivotal/RabbitMQ

和:

嗨,彼得,

解决方案C实际上非常合理.如果您正在尝试防范网络故障或群集分区,那么使用多个连接到同一服务器并没有多大好处.如果一个连接死亡,它们都可能会死.包装和恢复连接/通道工作正常,正如迈克尔所说,你也可以查看Lyra,因为它处理了为你恢复资源所涉及的各种角落案例.

干杯,乔纳森

阅读完整主题:

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

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