Асинхронные задачи в Django с использованием Celery и Redis: практическое руководство

Автор: Javohir Abdullayev · · Django

Асинхронные задачи в Django с использованием Celery и Redis: практическое руководство

Введение: почему в проектах на Django необходима асинхронность?

В веб-приложениях пользовательский опыт (UX) и скорость отклика системы являются одними из ключевых факторов успеха. Представьте, что после регистрации пользователя ему отправляется письмо с подтверждением или генерируется объемный PDF-отчет. Если эти операции выполняются напрямую в цикле «запрос-ответ» (request-response) Django, пользователю придется ждать загрузки страницы в течение нескольких секунд.

Самый эффективный способ решить эту проблему — вынести тяжелые и ресурсоемкие процессы в фоновый режим (background tasks). В этом практическом руководстве мы с нуля научимся выполнять асинхронные задачи в приложении Django с помощью Celery и Redis.

Необходимые технологии и архитектура

В нашем проекте будут взаимодействовать три основных компонента:

  • Django: основной веб-фреймворк и логика API.
  • Redis: выступает в роли брокера сообщений (message broker), сохраняя задачи в очереди (queue).
  • Celery: инструмент для приема и выполнения асинхронных задач в фоновом режиме (воркер / worker).

Шаг 1: Установка библиотек

Установите следующие пакеты в виртуальное окружение (venv) вашего проекта:

pip install django celery redis

Также на вашем компьютере или сервере должен быть установлен и запущен сервер Redis. Чтобы проверить это, введите в терминале следующую команду:

redis-cli ping
# Ответ: PONG

Шаг 2: Настройка Celery в проекте Django

Предположим, наш проект называется config. В основной директории проекта (там, где расположен settings.py) создайте файл celery.py:

import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')

app = Celery('config')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

Затем экспортируем приложение Celery в файле __init__.py в той же директории:

from .celery import app as celery_app

__all__ = ('celery_app',)

Шаг 3: Добавление настроек Redis в settings.py

Чтобы Celery знал, через какой брокер подключаться, добавьте следующие настройки в конец файла settings.py:

CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Tashkent'

Шаг 4: Создание асинхронной задачи (Task)

Теперь в вашем приложении (например, в приложении notifications) создайте файл tasks.py и напишите пример задачи:

from celery import shared_task
import time

@shared_task
def send_welcome_email(user_email):
    # Имитация: отправка письма занимает 5 секунд
    time.sleep(5)
    print(f"Приветственное письмо отправлено на адрес {user_email}!")
    return f"Письмо успешно отправлено: {user_email}"

Шаг 5: Вызов задачи через View

Вместо прямого вызова функции мы отправляем ее в фоновый режим с помощью метода .delay():

from django.http import JsonResponse
from .tasks import send_welcome_email

def register_user_view(request):
    user_email = request.GET.get('email', 'foydalanuvchi@pycoder.uz')
    # Отправляем асинхронную задачу в очередь
    send_welcome_email.delay(user_email)
    
    return JsonResponse({
        'status': 'success',
        'message': 'Пользователь зарегистрирован, письмо отправляется в фоновом режиме!'
    })

Шаг 6: Запуск Celery Worker

Для полноценной работы системы понадобятся два отдельных окна терминала. В первом терминале запустите сервер Django:

python manage.py runserver

Во втором терминале запустите процесс Celery worker:

celery -A config worker -l info

Теперь при отправке запроса на указанный URL-адрес представления пользователь мгновенно (за несколько миллисекунд) получит ответ, а 5-секундная ресурсоемкая операция будет автономно выполнена в окне Celery worker.

Заключение и лучшие практики

Связка Celery и Redis — один из самых надежных способов масштабирования проектов на Django и обеспечения устойчивости к высоким нагрузкам. В реальных проектах всегда обращайте внимание на следующее:

  • Задачи должны быть идемпотентными (повторное выполнение не должно приводить к нежелательным побочным эффектам).
  • Не передавайте крупные объекты (например, экземпляры моделей Django) в качестве аргументов задачи — передавайте только их идентификаторы (primary key).
  • Для обработки ошибок используйте параметры autoretry_for.

Теги: #Django #Celery #Redis #Backend #Python