Django и Celery. №1. Установка

Вступление

В этом руководстве по Django Celery я расскажу о

  1. Как настроить Celery с Django
  2. Как протестировать задачу Celery в оболочке Django
  3. Как контролировать Celery с помощью Flower

Вы можете получить исходный код этого проекта в конце этого руководства.

Зачем проекту Django нужен Celery

Celery может помочь запускать задачи рабочем процессе вместо web-процесса, поэтому в web-процессе мы можем немедленно вернуть HTTP-ответ (даже если задача worker process все еще выполняется) нашему пользователю, цикл запроса не будет заблокирован, и пользовательский интерфейс будет отзывчивым.

Ниже приведены некоторые примеры использования Celery.

  • Вы создали приложение для комментариев, которое поддерживает операции упоминания, пользователь может использовать "@"  чтобы упомянуть другого пользователя, и они будут получать уведомления по электронной почте. Если один пользователь упоминает 10 человек в одном комментарии, веб-процессу необходимо обработать и отправить 10 электронных писем. Иногда это может занять много времени (сеть, сервер и другие факторы), но Celery может позволить вам отправлять электронные письма в фоновом процессе, и вы можете вернуть HTTP-ответ пользователю, чтобы ему не нужно было ждать.

  • Когда пользователь загружает изображение в ваше веб-приложение, вам необходимо создать миниатюру, вы можете выполнить задачу в рабочем процессе

  • Вам нужно выполнить некоторую периодическую работу, например, создать ежедневный отчет, очистить данные просроченной сессии. Вы можете позволить Celery помочь отправить задачу в заданное время в worker process.

Когда вы создаете веб-приложение, вы должны попытаться сделать время отклика вашего веб-приложения ниже 500 мс, если некоторое время отклика велико, вы должны выяснить причину и попытаться ее решить. В решении этой проблемы может помочь Celery.

Celery VS RQ

RQ (Redis Queue) - еще одна библиотека Python, которая может помочь вам решить вышеуказанные проблемы.

Основная логика RQ (Redis Queue) и Celery одинакова (Producer/Consumer Pattern), здесь я бы сравнил их и дал вам лучшее понимание.

  • RQ (Redis Queue) прост в освоении, и его цель - снизить барьер для использования async worker. В нем отсутствуют некоторые функции, и его можно использовать только с Redis и Python.

  • Celery предоставляет нам больше функций, поддерживает множество различных серверных программ и более гибкий, поэтому документ немного сложен, и новичок может быть немного запутан.

Поскольку Celery может помочь мне лучше решить некоторые проблемы, я предпочитаю Celery, и я написал эту статью, чтобы помочь читателю (особенно новичку) быстро изучить Celery!

Брокер сообщений и бэкэнд результатов

Брокер сообщений - это хранилище, которое взаимодействует как транспорт между производителем и потребителем.

Из документа Celery рекомендуется брокер сообщений (message broker) RabbitMQ, потому что он поддерживает AMQP (Расширенный протокол очереди сообщений)

Но во многих случаях нам не нужно использовать функции AMQP и другие message broker, такие как Redis, тоже нормально.

Бэкэнд результатов - это хранилище, в котором сохраняется информация о результатах и ​​ошибках или задача Celery.

Redis здесь рекомендуется.

Как настроить Celery

Далее я покажу вам, как импортировать Celery worker в ваш проект Django.

Мы будем использовать Redis в качестве брокера сообщений и бэкэнда результатов, поэтому его будет немного проще настроить. Но вы можете выбрать предпочитаемого брокера сообщений и бэкэнд результатов в зависимости от ваших требований.

Используйте Docker, чтобы подготовить среду разработки

Если вы работаете на Linux или Mac, вы можете использовать диспетчер пакетов, чтобы настроить Redis за вас. (brew, apt-get install), однако я хотел бы порекомендовать вам попробовать Docker, чтобы установить сервер Redis.

  1. Вы можете скачать docker client здесь Get Docker

  2. Затем попробуйте запустить службу Redis
    $ docker run -p 6379:6379 --name some-redis -d redis

Команда выше запустит redis службу на127.0.0.1:6379

  1. Если вы хотите использовать здесь RabbitMQ в качестве брокера сообщений, вам просто нужно изменить приведенную выше команду, чтобы она работала.

  2. Закончив работу, вы можете закрыть контейнер Docker, и окружение вашего хост-компьютера по-прежнему будет чистым.

Затем давайте импортируем Celery в наш проект Django.

Создать проект django

# создайте новый python virtualenv и активируйте 
$ pip install django == 2 .2
$ django-admin startproject django_celery_example
$ python manage.py startapp опросы

Ниже представлена ​​структура проекта

.
├── django_celery_example
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── опросы
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── миграции
    │ └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

celery.py

Далее приступим к установке и настройке Celery.

# это установит Celery и redis-py
$ pip install -r requirements.txt

Создайте django_celery_example/celery.py рядом с django_celery_example/wsgi.py

"""
Celery config file

https://docs.celeryproject.org/en/stable/django/first-steps-with-django.html

"""
from __future__ import absolute_import
import os
from celery import Celery

# this code copied from manage.py
# set the default Django settings module for the 'celery' app.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery_example.settings')

# you change change the name here
app = Celery("django_celery_example")

# read config from Django settings, the CELERY namespace would make celery 
# config keys has `CELERY` prefix
app.config_from_object('django.conf:settings', namespace='CELERY')

# load tasks.py in django apps
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task
def add(x, y):
    return x / y

init .py

Продолжаем изменять django_celery_example/__init__.py

from __future__ import absolute_import, unicode_literals

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ('celery_app',)

settings.py

Поскольку Celery может читать конфигурацию из файла настроек Django, мы можем добавить туда конфигурацию для лучшего управления.

CELERY_BROKER_URL = "redis://127.0.0.1:6379/0"
CELERY_RESULT_BACKEND = "redis://127.0.0.1:6379/0"

Есть кое-что, о чем следует помнить.

Когда вы проверяете документ Celery, вы увидите, что broker_url - это ключ конфигурации, который вы должны установить для брокера сообщений, в приведенном выше celery.py

  1. app.config_from_object('django.conf:settings', namespace='CELERY') скажите Celery, чтобы он считывал значение из CELERY пространства имен, поэтому, если вы установите его broker_url в файле настроек Django, этот параметр не будет работать. Это правило также применяется для всех ключей конфигурации Celery в документе.

  2. Некоторые ключи конфигурации различаются между Celery 3 и Celery 4, поэтому, пожалуйста, проверьте документацию при выполнении конфигурации.

Отправить работу в Celery

Теперь настройка конфигурации завершена, давайте начнем пробовать Celery и посмотрим, как это работает. Здесь мы будем запускать некоторые команды в другом терминале, но я рекомендую вам взглянуть на Tmux когда у вас будет время.

Сначала запустите Celery worker в одном терминале, django_celery_example - это имя приложения Celery, которое вы установили в django_celery_example/celery.py

$ celery worker -A django_celery_example --loglevel=info

[config]
.> app:         django_celery_example:0x1034783c8
.> transport:   redis://127.0.0.1:6379/0
.> results:     redis://127.0.0.1:6379/0
.> concurrency: 8 (prefork)
.> task events: OFF (enable -E to monitor tasks in this worker)

[queues]
.> celery           exchange=celery(direct) key=celery


[tasks]
  . django_celery_example.celery.add

Во-вторых, давайте запустим веб-приложение, которое поможет нам отслеживать задачу Celery (чуть позже я расскажу об этом подробнее).

$ flower -A django_celery_example --port=5555

Затем вы можете открыть, http://localhost:5555/ и вы увидите веб-панель, которая поможет вам проверить детали воркера Celery.

Далее входим Django shell и пытаемся отправить какие-то задачи Celery

$ python manage.py migrate
$ python manage.py shell
>>> from django_celery_example.celery import add
>>> task = add.delay(1, 2)

Ниже приведены некоторые моменты

  1. Мы используем xxx.delay для отправки сообщения брокеру сообщений, и рабочий процесс выбирает эту задачу и запускается.

  2. После того, как вы нажмете enter после ввода task = add.delay(1, 2), код скоро завершится (не заблокирован), но add метод все еще работает в рабочем процессе celery.

  3. Если вы проверите вывод терминала celery, вы увидите что-то вроде этого

03:54:40,072: INFO/MainProcess] Received task: django_celery_example.celery.add[6501dc00-d422-4832-b8ab-fc72a8311586]
03:54:50,082: INFO/ForkPoolWorker-8] Task django_celery_example.celery.add[6501dc00-d422-4832-b8ab-fc72a8311586] succeeded in 10.00722316399333s: 0.5

Рабочий процесс получил задачу в 03:54:40, и через 10 секунд задача была выполнена успешно.

Думаю, теперь у вас уже есть базовое представление о рабочем процессе. Попробуем еще один блок кода

>>> import time
>>> from django_celery_example.celery import add
>>> task = add.delay(1, 2)
>>> 
>>> for i in range(13):
>>>     time.sleep(1)
>>>     print(task.state, task.result)


PENDING None
PENDING None
PENDING None
PENDING None
PENDING None
PENDING None
PENDING None
PENDING None
PENDING None
SUCCESS 0.5
SUCCESS 0.5
SUCCESS 0.5
SUCCESS 0.5
  1. Когда мы вызываем delay метод, мы получаем task экземпляр, который мы можем использовать для запроса состояния и результата задачи.

  2. Здесь мы poll состояние и результат каждые 0,5 секунды, и вы можете видеть прогресс.

Затем давайте попробуем вызвать ошибку в работнике Celery и посмотрим, что произойдет.

>>> import time
>>> from django_celery_example.celery import add
>>> task = add.delay(1, 0)

>>> type(task)
celery.result.AsyncResult

# here we wait for about 10 seconds, and then check the state and result
>>> task.state
'FAILURE'

>>> task.result
ZeroDivisionError('division by zero')

Как видите, после вызова метода задержки мы получаем AsyncResul tэкземпляр.

Мы можем использовать его для многих полезных вещей, таких как

  1. Проверить состояние задачи.

  2. Проверьте возвращаемое значение задачи или сведения об исключении.

  3. Проверьте другие метаданные задачи.

Мониторинг Celery с помощью Flower

flower может позволить нам отслеживать Celery на удобной для пользовательского интерфейса веб-странице, потому что это может помочь нам лучше понять более подробную информацию о Celery, поэтому я решил поговорить об этом, прежде чем углубляться в дальнейшие исследования.

URL-адрес веб-панели управления: http://127.0.0.1:5555/

Пожалуйста, проверьте tasks страницу.

Вы должны обратить внимание на UUID столбец, который AsyncResult.id

Вы также можете получить аналогичные сведения об одной задаче с помощью кода ниже.

>>> from celery.result import AsyncResult
>>> # 10da60be-80f6-437f-af68-c339ac6ebd7c here is the UUID copied from web page
>>> task = AsyncResult('10da60be-80f6-437f-af68-c339ac6ebd7c')
>>> task.state
'FAILURE'
>>> task.result
ZeroDivisionError('division by zero')

Когда вы изучаете Celery, вы можете использовать Flower для понимания деталей.

При развертывании проекта на сервере Flower необязателен. Я имею в виду, что вы также можете использовать команды Celery, чтобы управлять приложением и проверять статус.

Заключение

В этом сообщении в блоге я рассказал о некоторых основных частях Celery. Желаю, чтобы вы уже хорошо понимали весь рабочий процесс.

https://www.accordbox.com/blog/how-to-setup-celery-django/

Вернуться на верх