Как настроить определение времени ожидания на сервере RabbitMQ? - PullRequest
17 голосов
/ 28 августа 2009

Я пробую RabbitMQ с этим привязкой Python.

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

Например, если вы убьете потребителя 1 раз и переподключитесь, 1/2 сообщения будут игнорироваться. Если вы убьете другого потребителя, то 2/3 сообщения будут игнорироваться. Если вы убьете третье, то 3/4 сообщения будут игнорироваться и т. Д.

Я пытался включить подтверждения, но, похоже, это не помогает. Единственное решение, которое я нашел, - это вручную остановить сервер и сбросить его.

Есть ли лучший способ?

Как воссоздать этот сценарий

  • Run rabbitmq.

  • Разархивировать эту библиотеку .

  • Скачать для потребителя и издателя здесь . Запустите amqp_consumer.py дважды. Запустите amqp_publisher.py, добавив в него некоторые данные и отметив, что он работает как положено. Сообщения принимаются в круговом стиле.

  • Убить один из процессов-потребителей с помощью kill -9 или диспетчера задач.

  • Теперь, когда вы публикуете сообщение, 50% сообщений будут потеряны.

Ответы [ 3 ]

11 голосов
/ 06 сентября 2009

Я не вижу amqp_consumer.py или amqp_producer.py в тарболе, поэтому воспроизвести ошибку сложно.

RabbitMQ завершает соединения, выпуская их неподтвержденные сообщения для повторной доставки другим клиентам, когда операционная система сообщает, что сокет закрыт. Ваши симптомы очень странные, потому что даже kill -9 должно привести к правильной очистке сокета TCP.

Некоторые люди заметили проблемы с сокетами, которые дольше сохраняются, чем при работе с межсетевым экраном или устройством NAT между клиентами AMQP и сервером. Может ли это быть проблемой здесь, или вы запускаете все на локальном хосте? Кроме того, в какой операционной системе вы используете различные компоненты системы?

ETA: Из вашего комментария ниже я предполагаю, что, пока вы работаете на сервере в Linux, вы можете запускать клиенты в Windows. Если это так, то может быть так, что драйвер Windows TCP неправильно закрывает сокеты, что отличается от поведения kill-9 в Unix. (В Unix ядро ​​должным образом закроет TCP-соединения для любого прерванного процесса.)

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

Хорошая новость 1019 *, однако, заключается в том, что AMQP поддерживает опцию «пульса» именно в этих случаях, когда сетевая структура не заслуживает доверия. Вы можете попробовать включить сердцебиение. Когда они включены, если сервер не получает трафик в течение настраиваемого интервала, он решает, что соединение должно быть разорвано.

Плохая новость 1023 *, однако, заключается в том, что я не думаю, что py-amqplib в настоящее время поддерживает сердцебиение. Хотя стоит попробовать!

5 голосов
/ 06 сентября 2009

RabbitMQ не имеет тайм-аута на подтверждение от клиента, что сообщение было обработано: см. это сообщение (может быть интересна вся цепочка). Некоторые существенные моменты из поста:

Модель AMQP ack для подписок и "тянуть" идентичны. В обоих случаях сообщение хранится на сервер, но недоступен для других потребители, пока это не было ack'ed (и удаляется), nack'ed (с basic.reject; хотя RabbitMQ не реализует это) или канал / соединение закрыто (при котором указать сообщение становится доступным другим потребителям).

и (мои акценты)

Время ожидания не истекло ACKs. Обычно это не проблема , поскольку общие случаи пропажи ack - сбой сети или клиента - приведет к получению соединения упал (и, таким образом, вызвать поведение описано выше). Еще, тайм-аут может быть полезным, скажем, иметь дело с живым, но не отвечающим Потребители . Что пришло в обсуждение до. Есть ли конкретный случай использования вы имеете в виду, что требует такой функциональности?

Возможно, проблема возникает, потому что в модели извлечения клиента серверу сложнее обнаружить разрыв соединения (в отличие от живого, но не отвечающего потребителя), особенно потому, что сервер, кажется, с радостью ждет подтверждения.

Обновление: В Linux вы можете подключить обработчики сигналов для SIGTERM и / или SIGKILL и / или SIGINT и, возможно, упорядоченно закрыть соединение с клиентом. В Windows, я полагаю, что закрытие из диспетчера задач вызывает Win32 TerminateProcess API, о котором MSDN говорит:

Если процесс завершается TerminateProcess, все темы процесс немедленно прекращается без шансов запустить дополнительный код. Это означает, что поток не выполнить код в обработчике завершения блоки. Кроме того, нет подключенных DLL уведомлены, что процесс отсоединение.

Это означает, что может быть трудно поймать завершение и закрыть его упорядоченным образом.

Возможно, стоит остановиться на списке RabbitMQ с вашим собственным вариантом использования для тайм-аута.

2 голосов
/ 04 сентября 2009

Пожалуйста, предоставьте еще несколько подробностей относительно компонентов, которые вы объявили. Обычно (и не зависит от реализации клиента) очередь со свойствами

  • эксклюзив и
  • автоудаление

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...