JavaRush /Курси /Модуль 4: FastAPI /Використання кількох воркерів для розподілу навантаження

Використання кількох воркерів для розподілу навантаження

Модуль 4: FastAPI
Рівень 14 , Лекція 2
Відкрита

У цій лекції ми детально розберемо, як використовувати кілька воркерів для розподілу навантаження, як вони взаємодіють з RabbitMQ, а також як правильно моніторити й керувати їхньою продуктивністю. Готові? Тоді розслабте лікті (щоб було зручніше натискати клавіші) і поїхали!

Ми вже наводили приклад із чергами в банку. Якщо ви коли-небудь стояли в черзі в банку (а хто ж не стояв?), то знаєте, що обслуговувати клієнтів швидше можна лише одним способом — відкрити більше «вікон». У світі асинхронних завдань роль таких вікон виконують воркери. Кожен воркер Celery — це окремий процес, який виконує завдання, що надходять із черги RabbitMQ.

Кілька воркерів — працює швидше: завдання обробляються одночасно, система більш стійка (один воркер впаде — інші продовжать роботу). Та й навантаження розподіляється рівномірніше. Одні плюси!

RabbitMQ, як черга повідомлень, автоматично розподіляє завдання між воркерами. Принцип тут простий: pull-модель, де воркери самі «запитують» завдання у черги. Наприклад:

  • Воркери A, B, C підключені до однієї черги.
  • Щойно воркер A завершує завдання, він запитує наступне.
  • RabbitMQ видає це завдання першому воркеру, який його запитав.

Отже, завдання розподіляються автоматично, без необхідності «говорити» RabbitMQ, кому що надсилати. Це схоже на столову: кухар готує страви, а офіціанти беруть підноси, щойно звільняються.


Запуск кількох воркерів

Запуск кількох воркерів — це не магія й не шаманство. Все, що потрібно зробити, — створити кілька процесів, кожен із яких буде виконувати роль воркера. Давайте подивимось, як це зробити на практиці.

Команда для запуску воркерів у Celery виглядає так:


celery -A my_project worker --loglevel=info

Щоб запустити кілька воркерів, можна просто виконати команду кілька разів у різних терміналах. Але є й елегантніший спосіб.

Celery дозволяє вказати кількість процесів для одного воркера. Це робиться за допомогою флага --concurrency. Наприклад:


celery -A my_project worker --loglevel=info --concurrency=4

Тут:

  • --concurrency=4 означає, що один воркер створить 4 процеси для виконання завдань.

Ви також можете запустити кілька окремих воркерів:


celery -A my_project worker --loglevel=info --hostname=worker1@
celery -A my_project worker --loglevel=info --hostname=worker2@

Ці команди створять два воркери з іменами worker1 і worker2.


Приклади архітектури з кількома воркерами

Кілька воркерів корисні, якщо у вас:

  • Велика кількість вхідних завдань.
  • Різні завдання вимагають різних ресурсів.
  • У системі є завдання з високим пріоритетом.

Наприклад, в e-commerce системі можуть бути завдання:

  • Обробка замовлень.
  • Відправка email-повідомлень.
  • Генерація звітів.

Логічно розділити такі завдання між різними воркерами: один буде обробляти тільки email, інший — замовлення, а третій займеться звітами.

Приклад розподілу завдань

Створимо два воркери: один для завдань з високим пріоритетом, другий — для низькопріоритетних.

  1. У налаштуваннях Celery вказуємо дві черги:

from kombu import Queue

CELERY_QUEUES = (
    Queue('high_priority', routing_key='high.#'),
    Queue('low_priority', routing_key='low.#'),
)

CELERY_ROUTES = {
    'tasks.process_order': {'queue': 'high_priority', 'routing_key': 'high.orders'},
    'tasks.send_email': {'queue': 'low_priority', 'routing_key': 'low.emails'},
}
  1. Запускаємо два воркери з прив'язкою до черг:

celery -A my_project worker --loglevel=info --queues=high_priority --hostname=worker_high@
celery -A my_project worker --loglevel=info --queues=low_priority --hostname=worker_low@

Тепер завдання будуть розподілятися залежно від їхнього пріоритету.


Налаштування та моніторинг воркерів

Celery має вбудовані інструменти для моніторингу. Команда celery status показує поточних активних воркерів:


celery -A my_project status

Вивід може виглядати так:


celery@worker_high: OK
celery@worker_low: OK

Інші корисні команди:

  • celery inspect active — показує поточні завдання, які виконують воркери.
  • celery inspect reserved — завдання, що чекають на виконання.
  • celery inspect stats — статистика роботи, включно з кількістю оброблених завдань.

Використання Flower для моніторингу

А ще у Celery є інструмент Flower — візуальний інтерфейс для моніторингу.

  1. Встановіть Flower:

pip install flower
  1. Запустіть Flower:

celery -A my_project flower
  1. Відкрийте браузер і перейдіть за адресою: http://localhost:5555.

Flower покаже інформацію про всі ваші воркери, черги і завдання в реальному часі.


Інструменти управління воркерами

Іноді треба перезапустити воркерів. Наприклад, якщо ви оновили код завдань. Використовуйте команду:


pkill -HUP -f 'celery worker'

Ця команда м'яко перезапустить усі воркери. Якщо хочете примусово завершити їхню роботу:


pkill -9 -f 'celery worker'

Керування ресурсами воркерів

Розумно обмежувати ресурси для кожного воркера, щоб уникнути перевантаження CPU чи пам'яті. Використовуйте такі параметри:

  • --concurrency=N — кількість процесів.
  • --prefetch-multiplier=X — кількість завдань, які воркер бере в роботу одночасно.
  • --max-tasks-per-child=N — обмежує число завдань, які може виконати процес воркера перед завершенням.

Приклад запуску:


celery -A my_project worker --concurrency=4 --prefetch-multiplier=1 --max-tasks-per-child=100

Тут:

  • Кожному процесу видається лише одне завдання (щоб мінімізувати використання пам'яті).
  • Процес завершиться після 100 завдань, щоб уникнути накопичення витоків пам'яті.

Підсумковий приклад

Давайте створимо воркерів для системи обробки даних. Нехай у нас є завдання:

  1. Запис даних у базу даних.
  2. Відправка повідомлень.

Створимо окремі черги й воркери:


CELERY_ROUTES = {
    'tasks.save_to_db': {'queue': 'db_queue'},
    'tasks.send_notification': {'queue': 'notifications_queue'},
}

Запуск воркерів:


celery -A my_project worker --loglevel=info --queues=db_queue --hostname=worker_db@
celery -A my_project worker --loglevel=info --queues=notifications_queue --hostname=worker_notifications@

Тепер worker_db буде обробляти завдання запису в БД, а worker_notifications — завдання відправки повідомлень. Ефективно й красиво!


Розподіл завдань між воркерами й чергами — потужний інструмент для підвищення продуктивності системи. Залежно від навантаження ви можете додавати чи видаляти воркери, робити їх «розумнішими» з QoS, а також керувати розподілом завдань за допомогою маршрутів.

Тепер залишається лише спробувати запустити свої воркери, а якщо щось піде не так... навіть найкращі інженери з цим стикалися. Головне — не здаватися!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ