С появлением на нашем хостинге возможности запуска Фоновых процессов, запуск и использование Celery значительно упростилось. Пожалуй, даже можно сказать, что до Фоновых процессов запустить Celery должным образом было невозможно, поскольку постоянное наличие в памяти сервера хостинга запущенного процесса celery никаким образом не гарантировалось.
Celery - это планировщик асинхронных задач (asynchronous task queue). Процесс celery, запускающий наши задачи, должен работать отдельно от процесса сайта и в случае перезапуска контейнера сайта он должен стартовать автоматически. Как раз функционал автоматического перезапуска процесса в случае рестарта, падения и тп и обеспечивается Фоновыми процессами.
Фоновые процессы привязаны к сайтам, а сайты располагаются внутри контейнеров. Ознакомиться с процессом создания сайта на python (django) можно в этой статье.
Далее мы будем считать, что сайт создан, нужная версия python установлена и настроена через Личный кабинет и вы зашли на сервер по ssh. Для этой статьи в качестве примера мы создали сайт с именем celery.na4u.ru
с развернутым на нем Django в связке с MySQL. При разворачивании сайта было автоматически создано django-приложение na4u
.
Кроме этого, для работы Celery нам потребуется Redis. Чтобы активировать Redis, нужно в Личном кабинете перейти на страницу вашего контейнера (Хостинг -> выбираем требуемый контейнер), нажать на кнопку “Настройка тарифа” и активировать опцию Redis.
В консоли сервера переходим в папку app
нашего сайта:
cd celery.na4u.ru/app
В вашем любимом текстовом редакторе, будь то vim, nano, mcedit и тп, создаем файл requirements.txt
следующего содержания:
django==4.1
celery
redis
django-celery-beat
django-celery-results
И теперь устанавливаем все прописанные в requirements.txt
зависимости:
pip install -r requirements.txt
Вновь берем свой любимый текстовый редактор и на этот раз вносим корректировки в файл na4u/settings.py
:
INSTALLED_APPS = [
...
'django_celery_beat',
'django_celery_results',
...
]
DATABASES = {
'default': {
...
'OPTIONS': {'charset': 'utf8', 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
},
}
CELERY_RESULT_BACKEND = 'django-db'
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler'
Теперь необходимо применить миграции для вновь добавленных django-приложений. Для этого в консоли сервера выполняем:
./manage.py migrate
Далее, в папке нашего проекта na4u
создаем файл celery.py
:
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
# this is also used in manage.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'na4u.settings')
app = Celery('na4u')
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
Наконец, отредактируем файл na4u/__init__.py
чтобы он выглядел следующим образом:
from .celery import app as celery_app # noqa
__all__ = ('celery_app',)
Таким образом, при запуске django наш celery.app
всегда будет импортирован.
Если до этого момента всё прошло удачно, мы можем запустить Celery в консоли:
celery -A na4u worker --beat
Но, как вы наверняка понимаете, если сейчас закрыть консоль, то Celery будет остановлен. Да и никаких задач наш Celery пока не выполняет. Давайте исправим это.
Создадим django-приложение в котором будет размещаться код асинхронно выполняемых задач:
python manage.py startapp tasks
Конечно же это приложение нужно добавить в список INSTALLED_APPS
в нашем settings.py
:
INSTALLED_APPS = [
...
'tasks',
...
]
Теперь в папке tasks создадим файл tasks.py:
from celery import shared_task
@shared_task
def add(x, y):
""" Супер сложная функция, требующая огромных вычислительных мощностей и поэтому запускаемая асинхронно """
return x + y
Убедиться что Celery теперь стартует и видит нашу вновь созданную функцию можно с помощью команды
celery -A na4u worker -l info --beat
Давайте сделаем чтобы Celery работал постоянно. Для этого в Личном кабинете в нашем контейнере находим сайт celery.na4u.ru
и переходим во вкладку Фоновые процессы:
И конечно же теперь нужно нажать на кнопку “Добавить процесс”. В появившемся окне в поле “Команда для запуска” мы пишем команду, которая запускает Celery:
cd ~/celery.na4u.ru/app && ~/celery.na4u.ru/.env/bin/celery -A na4u worker -l info --beat
Теперь нажмем на кнопку “Добавить и запустить” и Celery запустится.
Чтобы убедиться что запуск Celery прошел успешно, в консоли запустите команду:
tail -f ~/celery.na4u.ru/log/service-ID-runlog/current
где ID
- это уникальный идентификатор процесса, который отображается в личном кабинете в списке созданных вами фоновых процессов. Эта команда покажет текущий лог Celery, обновляемый в реальном времени.
Чтобы убедиться что Celery запущен и работает, в папке app
нашего сайта запускаем команду
./manage.py shell
И в консоли python выполняем:
In [1]: from tasks.tasks import add
In [2]: add(2, 2)
Out[2]: 4
In [3]: add.delay(2, 3)
Out[3]: <AsyncResult: 76674c7d-4ac5-4184-8c06-bc86c41181fc>
Собственно, вот и всё. Остается добавить, что после внесения изменения в код задач потребуется перезапуск процесса Celery. Это можно сделать двумя способами:
touch ~/celery.na4u.ru/reload