Розуміння попереднього отримання завдання із селери


79

Я щойно дізнався про варіант конфігурації CELERYD_PREFETCH_MULTIPLIER( docs ). За замовчуванням - 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) Я майже впевнений, що все ще бачу повідомлення "Отримав завдання від посередника" до завершення поточного завдання.
Генрік Хаймбуергер

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, він буде попередньо отримувати стільки завдань, скільки кількість працівників пулу (паралельність) у вузлі. Отже, якщо у вас була паралельність = n, максимальним завданням, попередньо вибраним вузлом, буде n.

Без цієї -Ofairопції для мене сталося те, що якщо один із робочих процесів пулу виконував давно запущене завдання, інші працівники у вузлі також припинять обробку завдань, попередньо отриманих вузлом. Використовуючи -Ofair, це змінилося. Незважаючи на те, що один із робітників у вузлі виконував тривалі завдання, інші не зупиняли обробку і продовжували обробляти завдання, попередньо отримані вузлом. Тож я бачу два рівні попереднього вибору. Один на рівні робочого вузла. Інший на рівні індивідуального працівника. -OfairЗдавалося, використання для мене відключило його на рівні працівників.

Як ACKS_LATEпов’язано? ACKS_LATE = Trueозначає, що завдання буде визнане лише тоді, коли завдання буде успішним. Якщо ні, я припускаю, що це відбудеться, коли його отримає працівник. У разі попередньої вибірки завдання спочатку отримує працівник (підтверджується з журналів), але буде виконане пізніше . Я щойно зрозумів, що попередньо завантажені повідомлення відображаються у розділі "непідтверджені повідомлення" в rabbitmq. Тож я не впевнений, що встановлення його Trueвкрай необхідне. У нас так чи інакше були поставлені наші завдання таким чином (пізно) з інших причин.


Дякуємо, що досі внесли свій вклад у це питання! Не могли б ви додати трохи детальніше? Наприклад, ви пишете, -Ofairмає "різний ефект", але не те, як відрізняється ефект. Крім того, ви виховуєте CELERY_ACKS_LATE, як це робили інші раніше, але досі ніхто не зумів пояснити мені, яке відношення має цей атрибут до відключення попереднього завантаження.
Генрік Хаймбуергер

У мене була та сама проблема, що працювала з бекендом 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

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


Я створив PR-розгляд цієї справи, він буде доступний у celery
gCoh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.