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

Я использую производителя RabbitMQ для отправки длительных задач (30 минут+) потребителю. Проблема в том, что потребитель все еще работает над задачей, когда соединение с сервером закрыто и запрашивается неподтвержденная задача.

из исследования я понимаю, что либо пульс или увеличено время ожидания подключения можно использовать для решения этой проблемы. Оба эти решения приводят к ошибкам при их попытке. Читая ответы на подобные сообщения я также узнал, что многие изменения были реализованы в RabbitMQ с момента публикации ответов (например, тайм-аут сердцебиения по умолчанию изменился на 60 с 580 до RabbitMQ 3.5.5).

при указании сердцебиения и времени ожидания заблокированного соединения:

credentials = pika.PlainCredentials('user', 'password')
parameters = pika.ConnectionParameters('XXX.XXX.XXX.XXX', port, '/', credentials, blocked_connection_timeout=2000)
connection = pika.BlockingConnection(parameters)

channel = connection.channel()

отображается следующая ошибка:

TypeError: __init__() got an unexpected keyword argument 'blocked_connection_timeout'

при указании heartbeat_interval=1000 в параметрах соединения отображается аналогичная ошибка:TypeError: __init__() got an unexpected keyword argument 'heartbeat_interval'

и аналогично для socket_timeout = 1000 в отображается следующая ошибка: TypeError: __init__() got an unexpected keyword argument 'socket_timeout'

я запускаю RabbitMQ 3.6.1, pika 0.10.0 и python 2.7 на Ubuntu 14.04.

  1. почему вышеуказанные подходы приводят к ошибкам?
  2. можно ли использовать подход сердцебиения там, где есть длительная непрерывная задача? Например, можно ли использовать heartbeats при выполнении больших соединений с базой данных, которые занимают 30 + минут? Я за подход к сердцебиению, так как много раз трудно судить, как долго такая задача как база данных join займет.

Я прочитал ответы на подобные вопросы

обновление: running код из документации pika производит ту же ошибку.

1 ответов


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

возможно, сердцебиение может помочь сохранить ваше соединение живым, если ваша сетевая настройка такова, что бездействующие TCP/IP-соединения принудительно отбрасываются. Если это не так, изменение сердцебиения не поможет.

изменение времени ожидания соединения не поможет вообще. Этот параметр используется только при первоначальном создании соединение.

Я использую производителя RabbitMQ для отправки длительных задач (30 минут+) потребителю. Проблема в том, что потребитель все еще работает над задачей, когда соединение с сервером закрыто и запрашивается неподтвержденная задача.

для этого есть две причины, обе из которых вы уже столкнулись:

  1. соединения падают случайным образом, даже при лучших обстоятельствах
  2. повторный запуск a процесс из-за повторного сообщения в очереди может вызвать проблемы

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

вам понадобится система записи (возможно, с базой данных), которая отслеживает статус данного задания.

для потребителей поднимает сообщение и запускает процесс, он должен сразу же подтвердить сообщение и отправить сообщение о состоянии "started" в систему записи.

по завершении процесса отправьте еще одно сообщение, чтобы сказать, что это сделано.

Это не решит проблему с удаленным соединением, но ничего не решит 100% в любом случае. Вместо этого он предотвратит повторную очередь сообщений при сбросе соединения.

Это решение вводит другое проблема, однако: когда длительный процесс завершается сбоем, как вы возобновляете работу?

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