Практически в каждом приложении есть длительные задачи – например, отправка электронных писем, обработка файлов, генерация отчетов, парсинг веб-страниц и т. д. Когда количество подобных задач растет, их выполнение в стандартном потоке запросов может негативно повлиять на отзывчивость приложения, а при повышенной нагрузке – и вовсе привести к его полной недоступности, что отразится на пользовательском опыте.
Ведь, согласитесь, каждый пользователь хочет, чтобы приложение оперативно отвечало на запросы, и расстраивается, если этого не происходит.
Чтобы всего этого не случилось, можно использовать специальные инструменты. К примеру, если вы программируете на Python и работаете с Django, одним из возможных решений может стать использование связки Django и Celery.
О том, как она работает и чем может помочь, рассказываем в этой статье.
Для чего подходит связка Django и Celery
Для начала – буквально несколько слов о том, как работает Celery.
Celery – это распределенная система очередей задач, которая позволяет выполнять их в фоновом режиме, то есть отдельно от основного HTTP-запроса, не заставляя пользователя ждать их завершения. Как только вы интегрируете Celery в свое приложение, вы можете отправлять трудоемкие задачи в очередь – чтобы ваше приложение продолжало оперативно реагировать на запросы пользователей.
Таким образом, Django и Celery позволяют снять с приложения нагрузку, связанную с обработкой ресурсоемких операций, которые могут работать независимо от основного потока, а также назначать заданное время для обработки событий и выполнять повторяющиеся задания.
Подобные возможности помогают выполнять в фоне буквально всё, просто настроив Celery, – примеры использования этой системы могут быть самыми разными: в очереди можно выполнять отправку писем, анализ данных, обработку изображений, генерацию отчетов и т. д.
Чтобы выполнять это и многое другое, потребуется настройка Celery – вот простой алгоритм для примера:
- Выбор брокера сообщений
К примеру, можно выбрать Redis (REmote DIctionary Server – сетевое журналируемое хранилище данных типа “ключ” – “значение”).
В этом случае для установки Redis непосредственно на сервер с Ubuntu необходимо ввести команду:
sudo apt install redisА для запуска в Docker-контейнере введите команду:
docker run -d -p 6379:6379 redis- Установка пакетов в виртуальную среду
Это можно сделать через стандартные инструменты Python, вот команда для установки пакетов через pip:
pip install celeryПосле этого можно использовать Celery – асинхронный метод обработки практически готов, осталось лишь подключить и настроить само приложение, из которого должны поступать задания.
- Создание экземпляра приложения
В папке celery_django необходимо создать файл celery.py, затем открыть его в редакторе и внести следующий фрагмент:
import os
from celery import Celery
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "celery_django.settings")
app = Celery("celery_django")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()При этом в файл __init__.py следует добавить:
from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app
__all__ = ('celery_app',)Затем в файл settings.py следует внести такие строки:
CELERY_BROKER_URL = "redis://127.0.0.1:6379/0" (эта строка указывает, откуда система распределения процессов будет брать задания)
CELERY_RESULT_BACKEND = "redis://127.0.0.1:6379/0" (эта строка содержит адрес для регистрации результатов)
В данном примере адреса совпадают, поскольку используется одна и та же база Redis.
- Определение задач
Создайте файл tasks.py:
from celery import Celery
app = Celery('tasks', broker='your_broker_url')
@app.task
def add(x, y):
return x + y.@app.task – это декоратор из библиотеки Celery в Python, который используется для объявления функции как асинхронной задачи. В данном примере функция складывает значения X и Y.
При этом в Celery предусмотрено несколько методов для асинхронного вызова задач и управления их выполнением – вот основные:
task.delay(*args, **kwargs)– короткий способ вызвать задачу асинхронно;chain(tasks)– последовательное выполнение задач (результат одной передается следующей);group(tasks)– параллельное выполнение набора задач, результат возвращается в виде GroupResult;map(func, iterable)– можно использовать для распределения вызовов одной задачи по множеству аргументов.
Сегодня Celery выбирают для самых разных задач: отправки автоматических писем, построения системы адаптации сотрудников, обработки файлов, распределенных вычислений, запуска задач на периодической основе и т. д.
Поделимся примером, как можно запустить Celery для выполнения отправки писем в фоновом режиме.
Как выполнять фоновую отправку писем с Django и Celery
Разберем возможности Celery на конкретном примере для отправки почты с формы – в этом нам поможет репозиторий.
Итак, клонируем репозиторий и переходим в его директорию:
git clone https://github.com/stuartmaxwell/django-celery-example.git
Этот репозиторий представляет собой небольшой пример отправки почты с формы, где сам процесс отправки выполняется в фоне воркером Celery и не блокирует работу самого сайта.
Также нам потребуется локальный контейнер redis – запустим его следующей командой:
podman run -d --name celery-redis -p 127.0.0.1:6379:6379 docker.io/valkey/valkeyТеперь установим зависимости:
uv syncИ укажем в celery_project/settings.py настройки SMTP для отправки:
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.beget.com" # add your own settings here
EMAIL_PORT = "2525" # add your own settings here
EMAIL_HOST_USER = "example@betutorial.ru" # add your own settings here
EMAIL_HOST_PASSWORD = "REDACTED" # add your own settings here
EMAIL_USE_TLS = False # add your own settings here
DEFAULT_FROM_EMAIL = "example@betutorial.ru" # your email addressВыполним миграции:
uv run manage.py migrate
А также запустим процессы сервера Django:
uv run manage.py runserver
И Celery:
uv run celery -A celery_project worker -l info -P solo
После чего перейдем по адресу 127.0.0.1 в браузере и отправим письмо:

В логах сервера Django увидим, что запросы к веб-серверу выполнялись моментально, задержки на отправку не было:

Теперь посмотрим, что происходило за кулисами:

Разберем происходящее по порядку:
- Celery ждет появления ивентов в Redis.
- Django поместил ивент отправки почты в Redis при получении запроса на форму обратной связи.
- Celery получает ивент, пытается отправить письмо, в случае успеха логирует информацию об успешном выполнении.
Для примера – ключи, находящиеся в Redis:

Осталось лишь проверить, отправлено ли письмо:

Вот и всё, мы убедились, что письмо отправлено.
Если вы хотите попробовать выполнять фоновые задачи, используя Django и Celery, то готовый сервер с Django можно развернуть буквально в пару кликов, а перед использованием Celery рекомендуем ознакомиться с документацией.
FAQ о Django и Celery
В качестве брокера сообщений можно использовать RabbitMQ, Redis, Apache Kafka и т. п.
Celery может использоваться с любыми Python-приложениями и фреймворками (например, Flask, FastAPI или Pyramid).
Да, каждая отправка в очередь создает отдельный экземпляр задачи, который может выполняться воркерами параллельно.
Это можно сделать с помощью параметров воркера (--concurrency, --autoscale) или настроек очереди и квот (task_annotations, rate_limit).
Заключение
Если вы освоили Python, создали с его помощью полноценное приложение и уже готовы показать его широкой аудитории и единственное, что вас беспокоит, – ложка дегтя в виде длительных задач, будь то отправка электронных писем, обработка файлов, генерация отчетов, парсинг веб-страниц и т. д., то связка Django и Celery может вам помочь.
Таким образом можно повысить отзывчивость приложения, эффективно обрабатывать фоновые задачи, масштабировать нагрузку и улучшить пользовательский опыт, а также снизить риски перегрузки сервера и простоев.
Надеемся, эта статья была для вас полезна, а длительные задачи не помешают развивать ваш проект 🙂
Если у вас возникли вопросы, свяжитесь с нами удобным для вас способом – и мы обязательно ответим. Также ждем вас в нашем официальном Telegram-канале, а пообщаться на любую тему с коллегами по цеху и сотрудниками Beget вы можете в нашем чате.