Как я могу (могу ли я?) Обнаружить ошибку создания очереди RabbitMQ? - PullRequest
1 голос
/ 02 апреля 2019

Я пытаюсь обойти условие гонки в RabbitMQ, связанное с тем, что сервер не получает своевременно исключительные очереди после отключения сети / сокета, и это приводит к сбою кода восстановления на клиенте. Это не код, который я разработал или написал, и я довольно новичок в RabbitMQ и Spring. Мы также используем более старую версию Spring-Rabbit, 1.7.0.RELEASE, поэтому многие из новых функций, которые я мог бы использовать для решения этой проблемы, недоступны. Обновление до новейшего кода является опцией, но для этого потребуется полный набор регрессионных тестов, и мы предпочли бы что-то более простое в качестве кратковременного исправления, чтобы мы могли быстро выйти из строя. Затем мы можем свернуть обновление и необходимые изменения в более позднюю версию, где у нас будет время, чтобы протестировать ее должным образом.

Проблема довольно проста. У нас есть приложение на Java-сервере, которое создает именованную очередь, в которую все клиенты могут отправлять сообщения. Каждый из наших Java-клиентов создает именованную (имя на основе хоста) эксклюзивную очередь автоматического удаления для получения сообщений с сервера. Он настроен как эксклюзивный, потому что мы не хотим, чтобы какой-либо другой клиент использовал ту же очередь, так как все сообщения в этой очереди предназначены для клиента, создавшего очередь. Я понимаю, что создание именованных исключительных очередей, подобных этой, является плохой идеей, и что предпочтение отдается сгенерированным сервером именам очередей, но именно так система была реализована, и ее исправление теперь потребовало бы большого количества обратно несовместимых изменений и еще большего количества тестирования ...

Проблема возникает при сбое в сети, когда соединение с сокетом прекращается. Клиент обнаруживает это и пытается восстановить соединение, а также очередь и т. Д. Похоже, что существует состояние гонки, при котором сервер RabbitMQ не пожинает существующую очередь, пока клиент не попытался создать очередь несколько раз, но не удалось. и отключил соединение. Сервер RabbitMQ, в конце концов, пожинает очередь, но к тому времени клиент не работает и не восстанавливается.

Чтобы обойти проблему, я попытался создать неэксклюзивную очередь и установить для потребителя исключительную (которая фактически уже была). Это прекрасно работает и решает условия гонки. Однако наличие очереди, не являющейся исключительной, может вызвать существенный побочный эффект в ситуации ошибки, которой исключает исключительная очередь. Если второй клиент (client2) неправильно настроен и пытается использовать имя очереди, уже используемое другим клиентом (client1), создание очереди завершается неудачно, но соединение остается открытым, поэтому client2 все еще может отправлять сообщения на сервер, как если бы это был клиент1.

Исключительность очереди привела к сбою соединения, в результате чего было разорвано все соединение, и клиент2 не смог установить связь с сервером Rabbit в любом направлении. Удаление исключительной очереди и использование исключительной возможности потребителя означает, что client2 не может получать сообщения из очереди client1, но все равно может отправлять сообщения на наш сервер, как если бы это был client1. Это приводит к сбою управления client1, так как сервер получает противоречивую информацию о состоянии от двух разных клиентов.

В краткосрочном плане я хотел бы попытаться определить, что создание очереди не удалось на клиенте 2, и закрыть соединение так же, как это происходит в случае сбоя в исключительной очереди, так что клиент 2 не работает, но также не приводит к сбою client1. Тем не менее, я не могу понять, что делать, чтобы обнаружить сбой. Есть ли способ сделать это? Кажется, я ничего не могу найти ни в документации, ни в коде Spring AMQP.

Предложения

1 Ответ

0 голосов
/ 02 апреля 2019

Прежде всего, 1.7.0 старше двух лет;Вы должны хотя бы использовать последнюю версию 1.7.x, которая на момент написания статьи в 1.7.13.

SimpleMessageListenerContainer имеет свойство missingQueuesFatal, которое по умолчанию имеет значение true.Если установлено значение false, контейнер должен продолжать попытки бесконечно долго.

...