Общие сведения о предварительной выборке задач сельдерея

79

Я только что узнал о параметре конфигурации CELERYD_PREFETCH_MULTIPLIER( документы ). По умолчанию - 4, но (я считаю) я хочу, чтобы предварительная выборка была отключена или как можно меньше. Сейчас я установил его на 1, что достаточно близко к тому, что я ищу, но есть еще кое-что, чего я не понимаю:

  1. Почему это хорошая идея? Я действительно не вижу для этого причины, если только нет большой задержки между очередью сообщений и рабочими (в моем случае они в настоящее время работают на одном хосте и в худшем случае могут в конечном итоге работать на разных хостах с одними и теми же данными. центр). В документации упоминаются только недостатки, но не объясняются преимущества.

  2. Многие люди, кажется, устанавливают это значение в 0, ожидая, что таким образом можно будет отключить предварительную выборку (разумное предположение, на мой взгляд). Однако 0 означает неограниченную предварительную выборку. Зачем кому-то нужна неограниченная предварительная выборка, разве это не устраняет полностью параллелизм / асинхронность, для которой вы в первую очередь ввели очередь задач?

  3. Почему нельзя отключить предварительную выборку? В большинстве случаев это может быть не лучшим решением для производительности, но есть ли техническая причина, по которой это невозможно? Или это просто не реализовано?

  4. Иногда эта опция связана с CELERY_ACKS_LATE. Например. Роджер Ху пишет: «[…] часто на самом деле [пользователи] действительно хотят, чтобы рабочий зарезервировал столько задач, сколько дочерних процессов. Но это невозможно без включения поздних подтверждений […] »Я не понимаю, как связаны эти два варианта и почему одно невозможно без другого. Еще одно упоминание о связи можно найти здесь . Может кто-нибудь объяснить, почему эти два варианта связаны?

Хенрик Хеймбюргер
источник

Ответы:

32
  1. Предварительная выборка может улучшить производительность. Сотрудникам не нужно ждать обработки следующего сообщения от брокера. Общение с брокером один раз и обработка большого количества сообщений дает прирост производительности. Получение сообщения от брокера (даже от локального) обходится дорого по сравнению с доступом к локальной памяти. Рабочим также разрешено подтверждать сообщения пакетами.

  2. Нулевое значение предварительной выборки означает "без ограничений", а не без ограничений.

  3. Задокументировано, что установка предварительной выборки на 1 эквивалентна ее выключению, но это может быть не всегда (см. Https://stackoverflow.com/a/33357180/71522 )

  4. Предварительная выборка позволяет подтверждать сообщения партиями. CELERY_ACKS_LATE = True предотвращает подтверждение сообщений, когда они достигают работника

Мгер
источник
Благодарю. 2) Хорошо, но зачем кому-то «без определенного ограничения»? 3) Я почти уверен, что все еще вижу сообщения «Получена задача от брокера» до завершения текущей задачи.
Henrik Heimbuerger
1
AFAIK, установка предварительной выборки на 1 не эквивалентна ее отключению. Это наименьшее возможное значение (без взлома исходного кода) для предварительной выборки, которая, в свою очередь, представляет собой количество процессоров / ядер на текущей машине.
Рон Кляйн
1
@RonKlein Это не количество процессоров / ядер, это количество определенных вами рабочих Celery (которые в некоторых случаях могут быть одинаковыми, но обычно нет). Кроме того, если каждый воркер выполняет предварительную выборку одной задачи, затем выполняет ее, а затем выполняет предварительную выборку другой, это эквивалентно отключению предварительной выборки, поэтому IMHO ваше утверждение неверно. (Система всегда должна предварительно загружать столько задач, сколько есть рабочих, если она хочет, чтобы все рабочие были
загружены
3
Я думаю, что установка CELERYD_PREFETCH_MULTIPLIER в 1 в основном означает «выборку». Предварительная выборка подразумевается, когда значение установлено на> 1. Таким образом, фактически задачи, превышающие 1, «предварительно выбираются».
tigeronk2
3
Я запустить некоторые эксперименты, и (по крайней мере , с Redis брокера) настроек CELERYD_PREFETCH_MULTIPLIER = 1делает не отключить предварительную выборку. Он просто - как следует из названия - выполняет предварительную выборку только одной задачи за раз.
Дэвид Уолевер,
28

Старый вопрос, но все еще добавляю свой ответ, если это кому-то поможет. Мое понимание из некоторого начального тестирования было таким же, как и в ответе Дэвида Волевера. Я только что проверил это больше в сельдерее 3.1.19 и -Ofairдействительно работает. Просто он не предназначен для отключения предварительной выборки на уровне рабочего узла. Так будет и дальше. Использование -Ofairимеет другой эффект, который проявляется на уровне работника пула. Таким образом, чтобы полностью отключить предварительную выборку, сделайте следующее:

  1. Набор CELERYD_PREFETCH_MULTIPLIER = 1
  2. Набор CELERY_ACKS_LATE = True на глобальном уровне или уровне задачи
  3. Используйте -Ofairпри запуске рабочих
  4. Если вы установите для параллелизма значение 1, то шаг 3 не нужен. Если вам нужен более высокий уровень параллелизма, то шаг 3 важен, чтобы избежать резервного копирования задач на узле, который может запускать длительные задачи.

Добавляем еще несколько деталей:

Я обнаружил, что рабочий узел всегда выполняет предварительную выборку по умолчанию. Вы можете контролировать, сколько задач он предварительно выбирает, только используяCELERYD_PREFETCH_MULTIPLIER . Если установлено значение 1, он будет выполнять предварительную выборку только столько задач, сколько рабочих пула (параллелизм) в узле. Итак, если у вас есть concurrency = n, максимальное количество задач, предварительно загружаемых узлом, будет n.

Без этой -Ofairопции для меня произошло следующее: если один из рабочих процессов пула выполнял длительную задачу, другие рабочие в узле также перестали бы обрабатывать задачи, уже предварительно загруженные узлом. При использовании -Ofair, что изменилось. Даже если один из рабочих в узле выполнял длительные задачи, другие не прекращали обработку и продолжали обрабатывать задачи, предварительно загруженные узлом. Итак, я вижу два уровня предварительной выборки. Один на уровне рабочего узла. Другой - на уровне отдельного работника. Использование -Ofairдля меня, казалось, отключило его на рабочем уровне.

Как это ACKS_LATEсвязано? ACKS_LATE = Trueозначает, что задача будет подтверждена только в случае успешного выполнения задачи. Если нет, я полагаю, это произойдет, когда его получит рабочий. В случае предварительной выборки задача сначала получает рабочий (подтверждается из журналов), но будет выполнена позже . Я только что понял, что предварительно загруженные сообщения отображаются в rabbitmq в разделе «неподтвержденные сообщения». Поэтому я не уверен, что установка этого значения Trueабсолютно необходима. У нас все равно были поставлены задачи таким образом (позднее подтверждение) по другим причинам.

Ксрини
источник
Спасибо, что все еще ответили на этот вопрос! Не могли бы вы добавить немного подробностей? Например, ваше письмо -Ofairимеет «другой эффект», но не то, как этот эффект отличается. Кроме того, вы поднимаете вопрос CELERY_ACKS_LATE, как и другие раньше, но пока никому не удалось объяснить мне, какое отношение этот атрибут имеет к отключению предварительной выборки.
Henrik Heimbuerger
У меня была такая же проблема, когда я работал с бэкэндом Redis. У меня было 4 одновременных выполнения задачи, и когда одна начинала зависать, другие ждали, пока она завершится (а этого не произойдет) - убийство этого рабочего позволит возобновить выполнение других. У меня уже было, prefetch=1, celery_acks=Trueи когда я добавил, -Ofairисправлена ​​проблема, когда они ждали зависшего рабочего. К сожалению, проблема с зависшими рабочими по-прежнему не решена для меня, поэтому все рабочие в конечном итоге зависают, но по крайней мере они больше не делают это в одно и то же время.
JiminyCricket,
18

Просто предупреждение: на момент моего тестирования с брокером redis + Celery 3.1.15 все советы, которые я прочитал, относящиеся к CELERYD_PREFETCH_MULTIPLIER = 1 отключения предварительной выборки, явно неверны.

Чтобы продемонстрировать это:

  1. Набор CELERYD_PREFETCH_MULTIPLIER = 1
  2. Поставьте в очередь 5 задач, каждая из которых займет несколько секунд (например, time.sleep(5))
  3. Начните следить за длиной очереди задач в Redis: watch redis-cli -c llen default

  4. Начало celery worker -c 1

  5. Обратите внимание, что длина очереди в Redis сразу уменьшится с 5до3

CELERYD_PREFETCH_MULTIPLIER = 1 не препятствует предварительной выборке , а просто ограничивает предварительную выборку до 1 задачи на очередь.

-Ofair, несмотря на то, что говорится в документации , также не предотвращает предварительную выборку .

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

Дэвид Волевер
источник
1
Как упоминалось в других ответах, если вы также установите, CELERY_ACKS_LATE = 1вы эффективно отключите предварительную выборку.
jodag 04
11

Я не могу комментировать ответы Дэвида Волевера, поскольку мой стек недостаточно высок. Итак, я сформулировал свой комментарий как ответ, так как хотел бы поделиться своим опытом работы с Celery 3.1.18 и брокером Mongodb. Мне удалось остановить предварительную выборку следующим образом:

  1. Добавить CELERYD_PREFETCH_MULTIPLIER = 1 в конфиг сельдерея
  2. Добавить CELERY_ACKS_LATE = True в конфиг сельдерея
  3. Начните с сельдерея с опциями: --concurrency=1 -Ofair

Если оставить значение CELERY_ACKS_LATE по умолчанию, рабочий процесс по-прежнему выполняет предварительную выборку. Как и в случае с OP, я не совсем понимаю связь между предварительной выборкой и поздним подтверждением. Я понимаю, что говорит Дэвид: «CELERY_ACKS_LATE = True предотвращает подтверждение сообщений, когда они доходят до рабочего», но я не понимаю, почему поздние подтверждения несовместимы с предварительной выборкой. Теоретически упреждающая выборка по-прежнему позволяла бы подтверждать позднее право, даже если она не закодирована как таковая в сельдерее?

Поль-Арман Верхаеген
источник
2

С SQS в качестве брокера я испытал кое-что немного другое.

Настройка была:

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

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

Решение, которое заставляло рабочих продолжать трудиться, заключалось в установке

CELERYD_PREFETCH_MULTIPLIER = 0

Я могу только предположить, что acks_late не принимался во внимание при написании транспорта SQS.

gCoh
источник
Я создал PR для этого дела, он будет доступен в
celery