Как вы справляетесь с восстановлением из-за неправильного соединения с помощью 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 не так много говорит о восстановлении от неисправного соединения. Любой вход оценивается:)
Ответы
Ответ 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(истина):