Подтвердить что ты не робот

Как вы справляетесь с восстановлением из-за неправильного соединения с помощью RavbitMQ java-клиентской библиотеки?

Мне интересно узнать, как другие люди справляются с восстановлением из-за неправильного соединения, используя официальную клиентскую библиотеку 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 Connection и Channel классы - это классы, которые обрабатывают логику повторного подключения, потребитель должен знать только о классе WrappedChannel. При сбое соединения WrappedConnection будет иметь дело с восстановлением соединения и после подключения WrappedConnection автоматически создаст новые каналы и зарегистрирует потребителей.

Плюсы: он работает - это на самом деле решение, которое мы используем сегодня.

Минусы: Это похоже на хак, я думаю, что это то, что должно быть более элегантно обработано основной библиотекой.

Может быть, есть намного лучший способ? Документация API не так много говорит о восстановлении от неисправного соединения. Любой вход оценивается:)

4b9b3361

Ответ 1

Получите хорошие ответы в списке рассылки RabbitMQ, в основном предлагая решение C, как указано выше.

Решение C)

     

Wrap Connection и классы каналов - это классы, которые обрабатывают логику повторного подключения, потребитель должен знать только о   Класс WrappedChannel. При сбое соединения WrappedConnection   с возможностью восстановления соединения и после подключения   WrappedConnection автоматически создаст новые каналы и зарегистрирует   потребителей.

     

Плюсы: он работает - на самом деле это решение, которое мы используем сегодня.

     

Минусы: это похоже на взломать, я думаю, что это то, что должно быть обработано более элегантно лежащей в основе библиотекой.

Это то, что два клиента построили на вершине Java - Langohr и March Hare-do. Это не хак, а необходимая работа потому что восстановление соединения в настоящее время не выполняется Java клиент (это должно быть основной особенностью, если вы спросите меня).

Итак, это жизнеспособный подход.

Посмотрите на Лиру тоже: https://github.com/jhalterman/lyra.

MK

Инженер-программист, Pivotal/RabbitMQ

и

Привет, Питер,

Решение C на самом деле довольно разумно. Там нечего выиграть от использования нескольких подключений к одному и тому же серверу, если вы пытаетесь защищать от сбоев сети или кластерных разделов. Если один они все, скорее всего, будут. Обертывание и восстановление соединения/каналы работают нормально, и, как сказал Майкл, вы можете также проверьте Лиру, так как он обрабатывает различные угловые случаи в восстановлении ресурсов для вас.

Приветствия, Джонатан

Прочитайте полную версию здесь:

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

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

Ответ 2

Начиная с версии 3.3.0 вы можете использовать автоматическое восстановление, которое является новой функцией клиента Java. В руководстве по API Java (http://www.rabbitmq.com/api-guide.html#recovery)

Чтобы включить автоматическое восстановление соединения, используйте factory.setAutomaticRecovery(истина):