В нашей среде мы используем RabbitMQ и Celery на AWS для параллельной работы задач на многих узлах.
Недавно мы превратили RabbitMQ в кластер из трех узлов, сконфигурировали политику ha и добавили балансировку нагрузки AWS (ELB) для порта 5672 ко всем 3 узлам. Наши работники Celery и клиентский код используют DNS-сервер ELB в качестве URL-адреса брокера.
Мы заметили, что после этого изменения ожидающий завершения задач async будет генерировать исключение IOError: Socket closed
.
ELB отключит все холостые соединения через 60 секунд. У нас есть задачи, которые занимают несколько часов.
Установка BROKER_HEARTBEAT на значение ниже 60 разрешенных соединений падает на рабочих. Но мы не можем найти какой-либо настройки, которая будет поддерживать клиентское соединение.
Это правильный подход, чтобы ждать длительных задач с помощью Celery?
Обходной путь, который мы еще не тестировали, заключается в том, чтобы вспомнить метод AsyncResult.wait()
, пока он не завершится успешно. Так, например:
async_result = task.delay(params)
while True:
try:
async_result.wait()
break
except IOError:
pass
Мы используем:
- RabbitMQ 3.6.5
- Сельдерей 3.1.20
- Бекленок сельдерея - это pyamqp
- Бэкэнд результатов сельдерея - rpc