Context
Я недавно начал пытаться обновить Celery с 3.1.25 до 4.2.1.Мы используем Python 2.7.6, бэкэнд RabbitMQ (3.6) и драйвер pyamqp
.
Мы запускаем сельдерей с отключенными pidbox, наряду с --without-mingle
, --without-gossip
и --without-heartbeat
options.
У нас есть одна очередь, которая содержит только один тип задачи: задача ETA со временем выполнения в далеком (днях) будущем.Каждое задание выполняется за <1 мс, и они редко «приходят из-за».По большей части эти работники сидят и буферизуют задачи ETA в состоянии ETA, ожидая прибытия новой или время от времени ее выполнения. </p>
Несколько работников (параллелизм 1, prefork) прослушивают эту очередь.Для этих работников CELERYD_PREFETCH_MULTIPLIER
установлено значение 50.
Обычно, когда эти работники перезапускаются, задачи в RabbitMQ доставляются в очень короткие сроки.Через несколько минут или меньше: все задачи покидают состояние «готово» и остаются рабочими в «незанятом» состоянии.
Ранее, когда для CELERYD_PREFETCH_MULTIPLIER
было установлено значение 1, это занимало очень много времени.время для рабочих для буферизации задач (рабочие постепенно увеличивают свое QoS и RabbitMQ, впоследствии распределяя эти задачи среди рабочих и переводя их в незанятое состояние).После того как мы установили его на 50, процесс ребуферизации для очереди из 10 000 задач выглядит в RabbitMQ следующим образом:
Сразу после того, как все задачи были буферизованы,Celery начинает выполнять (очень мало) задач, для которых требуется ETA.
Задача
После обновления с сельдерея с 3.1.25 до 4.2.1, когда рабочие ETA перезапускаются, требуется оченьCelery долгое время увеличивал размер буфера QoS, чтобы перевести все сообщения в состояние «без упаковки» (и во внутреннюю очередь кучи для проверки ETA).Это занимает так много времени, что некоторые из ETA задач пропускаются.
Celery 4 увеличивает окно QoS намного медленнее (хотя оно неуклонно увеличивается), чем версия 3.
Я могучтобы реплицировать эту ситуацию локально на моем ноутбуке (с очередью, полной задач ETA, время прибытия которых составляет дни в будущем), а также на производстве.Сельдерей 3, кажется, увеличивает свое QoS и время от времени спит, но не очень долго.Сельдерей 4 также увеличивает QoS, но, по-видимому, спит гораздо чаще и дольше.Даже в режиме отладки информация не выдается, когда рабочие спят.
В этом тесте поведение Celery 4 выглядит следующим образом:
(Приход сообщений в 20:02 - это заполнение очереди задачами ETA перед запуском работника и началом теста).
Единственное, что изменяется между этими поведениями, - это версия Celery.
Это вызывает проблемы в работе, потому что, хотя работники могут быть недоступны в течение нескольких минут, а когда они перезапускаются (например, из-за развертывания кода), очень глубокие очереди только для ETA могут занять часы для повторной доставкирабочим.В течение этого времени задачи, чьи ETA находятся в прошлом, могут не подниматься.
Вопросы
- Почему доставка задач на основе предварительной выборки из очереди, содержащей только задачи ETA с будущимВ Celery 4 время прибытия намного медленнее, чем в Celery 3?
- Как можно восстановить поведение Celery 3, если не считать понижения?
Что я пробовал
- Обойти проблему, увеличив параллель.Производственная очередь только для ETA часто запускается с общим числом сообщений более 100 тыс. И параллельно с параллельным использованием 4 процессов (каждый из которых является
--concurrency=1
рабочим Celery на другом хосте).На Celery 3 общее время простоя / позднего ETA с 4 рабочими составило около 3 минут.На Celery 4 мы пытались увеличить число рабочих до 64, и очереди все еще требовалось более часа, чтобы достичь 0 сообщений в состоянии готовности. - Если посмотреть на источник Celery, ограничения скорости могут быть связаны сэта ситуация.Запуск Celery с
CELERY_DISABLE_RATE_LIMITS
не повлиял на поведение. - Я пытался установить
CELERYD_PREFETCH_MULTIPLIER
на 0 для затронутых работников.Это решает проблему (задачи перераспределяют задачи даже быстрее, чем в Celery 3), но создает худшую проблему: некоторые работники часто выходят из строя и исчерпывают память, пока система не достигнет равновесия между различными потребителями на разных хостах.Это создает сбои в мониторинге и много шума, и, если нет другой альтернативы, я бы не хотел полагаться на то, что работники «мчатся», чтобы получать сообщения как можно быстрее.Использование множителя с высоким значением, по крайней мере, в Celery 3, позволило нам по совпадению распределить ожидающие ETA сообщения более или менее равномерно по всем потребителям в кластере. - Я попытался вернуться к планировщику
-OFast
(Celery 4 изменил значение по умолчанию).Это не имело никакого эффекта. - Изменение значения
CELERYD_TIMER_PRECISION
также не имело никакого эффекта.