Подтвердить что ты не робот

Падение соединения сельдерея с AWS ELB и RabbitMQ

В нашей среде мы используем 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
4b9b3361

Ответ 1

Я полагаю, что вам нужно сделать, это увеличить тайм-аут на AWS ELB. Что происходит, соединение закрывается до завершения задачи. Вы можете выполнить это, выпустив следующую команду

elb-modify-lb-attributes myTestELB --connection-settings "idletimeout=3600" --headers

Это даст вам час для выполнения задачи. См. https://aws.amazon.com/blogs/aws/elb-idle-timeout-control/ для получения дополнительной информации об этом.

Если час недостаточно, вам придется отключить объединение пулов. Добавьте эти два параметра в конфигурацию celery

BROKER_POOL_LIMIT = None
BROKER_TRANSPORT_OPTIONS = {'confirm_publish': True}

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

Еще один вариант - сломать свою длинную задачу на более мелкие задачи! Это может означать больше кода, но в конечном итоге это может стоить.