Cat

Django 43. Подключаем Celery и Redis для фоновой отправки почты

В этом посте мы добавим поддержку Celery и Redis в наш Django-проект, чтобы отправлять электронную почту в фоновом режиме.

Все статьи

Icon Link

Дополнительные материалы

Icon Link

Реклама

Icon Link
Сайт на Django proDream 18 Июль 2024 Просмотров: 375

В синхронном программировании, которое используется во фреймворке Django, все действия выполняются последовательно: следующая команда начинает выполняться только после полного завершения предыдущей. В посте "Django 39. Капча и подтверждение регистрации по email" мы добавили отправку письма на электронную почту для подтверждения регистрации. В данный момент это является "узким" местом по производительности, доставляя пользователю дискомфорт из-за ожидания завершения отправки формы регистрации.

Для решения этой проблемы мы воспользуемся инструментом Celery. Celery — это асинхронный менеджер задач. Он выполняет задачи в фоновом режиме в отдельном процессе, что позволяет не нагружать основной процесс тяжёлыми операциями. Для взаимодействия между основным приложением (в нашем случае Django) и отдельным процессом "работника Celery" (Celery worker), Celery использует СУБД Redis или менеджер очередей RabbitMQ. Мы будем использовать Redis, так как он проще для новичков, а про RabbitMQ поговорим в другой раз.

Redis — это популярная СУБД типа "ключ-значение". Проще говоря, Redis хранит записи в виде JSON. Благодаря тому, что вся база данных загружена в оперативную память, Redis обеспечивает высокую скорость работы с данными.

В этом посте мы добавим поддержку Celery и Redis в наш Django-проект, чтобы отправлять электронную почту в фоновом режиме.

Пост является продолжением поста "Docker 8. Разворачивание Django-проекта в Docker compose", так как для Celery и Redis будем использовать Docker.

 

Запускаем Redis.

Первым делом необходимо запустить Redis. Для этого откроем docker-compose.yaml и добавим сервис redis со следующим содержимым:

redis:  
  image: redis  
  restart: always  
  volumes:  
    - ./redis-data:/data

 

Конфигурация порта

Новых параметров здесь нет, однако стоит отметить один момент. Если вы разрабатываете локально и хотите проверять работу Celery, то необходимо указать ключ ports:

ports:  
  - "6379:6379"

 

На VPS открывать порты сервисов "наружу" крайне нежелательно. Однако, если разработка ведётся локально вне Docker-контейнеров с самим Django-проектом, то следует либо установить Redis в систему, либо запустить контейнер с ним и указать порт, который будет доступен на вашей локальной машине.

 

Конфигурация переменных окружения

После того, как определили сервис для Redis, откройте .env файл Django-проекта и добавьте новую переменную окружения:

# Если используется первый вариант в связке всего Docker compose:
REDIS_URL=redis://redis:6379/0

# Если Redis используется локально:
REDIS_URL=redis://localhost:6379/0

 

Разберём URL-адрес подключения к Redis на примере варианта с паролем:

  • redis:// — Протокол для подключения.
  • адрес_сервера:6379 — Хост Redis-сервера и открытый порт.
  • /0 — Номер используемой базы данных, по умолчанию доступно от 0 до 15.

 

Установка зависимости Redis

Последним шагом в подготовке Redis будет установка Python-библиотеки. Выполним команду:

pip install redis

 

И обязательно добавим его в requirements.txt:

redis==5.0.5

 

Подключение Celery к Django.

Для подключения Celery к Django выполним несколько шагов.

 

Установка зависимостей.

Первым шагом будет установка Python-библиотеки Celery. Для этого выполним команду:

pip install celery

 

Также сразу добавим её в requirements.txt:

celery==5.4.0

 

Параметры Celery.

Откроем файл settings.py Django-проекта. Необходимо добавить два параметра:

  • CELERY_BROKER_URL — URL для подключения к брокеру сообщений. В нашем случае это Redis. Когда Celery получает задачу, она отправит необходимые для рабочего (Celery worker) данные в Redis. После этого рабочий увидит новую задачу и начнёт её выполнение в отдельном процессе.
  • CELERY_RESULT_BACKEND — URL для подключения к брокеру сообщений, указывающий Celery, куда отправлять результаты выполнения задач.

Обычно эти два параметра содержат идентичный путь, но всё зависит от потребностей и реализации. Возможно, вам потребуется получать результаты выполнения в другую Redis-БД.

Добавим эти параметры в settings.py:

CELERY_BROKER_URL = os.environ.get("REDIS_URL")  
CELERY_RESULT_BACKEND = os.environ.get("REDIS_URL")

 

Создание файла Celery-приложения

Для запуска Celery определим его точку входа. В директории Django-проекта рядом с файлом settings.py создадим файл celery.py.

В этом файле определим Celery-приложение, укажем настройки Django и включим автоматический поиск задач:

import os  
from celery import Celery  

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pressanybutton.settings")  

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

 

Разберём код:

  • Импортируем модуль os из стандартной библиотеки Python и класс Celery из библиотеки celery.
  • Устанавливаем переменную окружения DJANGO_SETTINGS_MODULE, если она ещё не установлена. Эта переменная указывает на модуль настроек Django, обычно в форме project_name.settings. В данном случае это pressanybutton.settings. Это нужно, чтобы Celery знал, где искать настройки Django.
  • Объявляем экземпляр класса Celery, передав в него имя для идентификации проекта.
  • Конфигурируем объект Celery использовать настройки из объекта settings модуля django.conf. Опция namespace='CELERY' означает, что Celery будет искать только те настройки, которые начинаются с префикса CELERY_, например, CELERY_BROKER_URL.
  • Последняя строка указывает объекту Celery автоматически обнаруживать и загружать задачи из установленных приложений Django. Celery будет искать модуль tasks.py в каждом установленном приложении.

 

Видимость Celery-приложения.

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

from .celery import app as celery_app  

__all__ = ('celery_app',)

 

Разберём код:

  • Импорт Celery-приложения: В первой строке мы импортируем экземпляр класса Celery, который определён в переменной app в файле celery.py.
  • Экспорт Celery-приложения: Во второй строке мы экспортируем импортированный объект app как celery_app. Это делается для того, чтобы Celery-приложение было доступно как модуль при импорте из других частей проекта.

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

 

Запуск Celery локально.

Во время разработки желательно всё проверять до загрузки на VPS. В этом блоке рассмотрим, как запускать Celery локально.

Для работы Celery необходим Redis. Убедитесь, что Redis запущен локально или удалённо и доступен для подключения.

 

Запуск Django и Celery

Откройте два терминала в директории проекта:

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

python manage.py runserver

 

Во втором терминале для запуска Celery выполните следующую команду:

celery -A pressanybutton.celery worker -l INFO

 

Для пользователей Windows

Возможны проблемы с запуском Celery на Windows. В этом случае используйте команду:

celery -A pressanybutton.celery worker -l INFO -P solo

 

Разберём команду:

  • celery - Запуск процесса приложения Celery.
  • -A pressanybutton.celery - Указание на использование рабочего модуля. В нашем случае это файл celery.py.
  • worker - Указание на то, что необходимо запустить рабочий процесс (Celery worker).
  • -l INFO - Уровень логирования. Уровень INFO выводит в консоль информационные сообщения о выполняемых процессах, помимо более серьёзных уровней логирования. Можно изменить на один из: INFO, DEBUG, WARNING, ERROR и CRITICAL.
  • -P solo - Актуально для пользователей Windows. Указывает на количество Celery-процессов. Параметр solo означает, что будет запущен только один процесс Celery.

 

Celery worker в Docker compose.

Поскольку Celery требует запуска в отдельном от Django-процессе, для его работы в Docker compose мы создадим новый сервис worker. Этот worker по сути будет копией контейнера с Django-проектом, но с отличием в команде запуска.

 

Настройка Docker compose

Откроем файл docker-compose.yaml и добавим новый ключ worker со следующим содержимым:

worker:  
  build: ./pressanybutton  
  command: celery -A pressanybutton.celery worker -l INFO  
  env_file:  
    - ./pressanybutton/.env  
  volumes:  
    - ./pressanybutton:/code  
  depends_on:  
    - web  
    - redis  
    - db

 

Пояснение конфигурации

Обратим внимание на ключевые параметры:

  • build: ./pressanybutton - Указывает путь к директории с проектом для сборки Docker-образа.
  • command: celery -A pressanybutton.celery worker -l INFO - Команда запуска рабочего Celery.
  • env_file: - ./pressanybutton/.env - Подключение файла окружения с переменными.
  • volumes: - ./pressanybutton:/code - Примонтирование директории проекта.
  • depends_on: - web, - redis, - db - Определение зависимостей: рабочий процесс Celery зависит от сервисов web (Django-проект), redis, и db.

 

Заключение.

Мы познакомились с Celery и Redis, подготовили Django для работы с Celery и запустили Celery worker.

Celery – это мощный и полезный инструмент для выполнения фоновых задач. С его помощью можно обрабатывать множество различных задач, не только в рамках Django. Примеры таких задач включают:

  • Формирование отчётов: Сбор данных, их анализ и генерация отчётов без задержки основной функциональности приложения.
  • Обработка данных: Выполнение ресурсоёмких операций, таких, как преобразование и очистка данных, агрегация и другие виды обработки.
  • Обработка изображений: Манипуляции с изображениями, такие, как изменение размера, применение фильтров или создание эскизов.
  • Отправка электронной почты: Автоматическая отправка писем, создание рассылок и уведомлений пользователям.
  • Периодические задачи: Выполнение задач по расписанию, например, очистка временных файлов, резервное копирование данных или синхронизация с внешними сервисами.

Использование Celery позволяет значительно разгрузить основной процесс приложения, улучшая его производительность и отзывчивость для пользователей.

В следующем посте мы рассмотрим, как настроить и использовать Celery для отправки электронной почты в фоновом режиме.

Автор

    Нет комментариев

    Реклама