Примеры работы с Celery

При разработке различных порталов/сайтов зачастую необходимо исполнять какую-то часть бизнес-логики асинхронно от действий пользователя.

 

К примеру запустить почтовую рассылку, скачку и конвертацию файлов и прочее.

Решить задачу можно собственноручно, написать прямую работу с какой-либо очередью сообщений, к примеру, RabbitMQ, либо даже Redis-ом, так как у него есть функционал подписывания и оповещения publish/subsrcibe.

Основная часть заказов по разработке веб-проектов мы проводим на Django, а в этом мире как самым типовым решением, покрывающим большинство задач, является Celery.

 

Celery – планировщик задач, который является прослойкой между очередью сообщений, типа RabbitMQ, и вашим кодом. Это позволяет писать не в терминах каких-то сообщений, которые вы потом еще должны будет проанализировать, чтобы выполнить нужны действия,а  а в терминах задач. Как правило задача – это обыкновенная python функция. Это упрощает разработку, позволяет  использовать уже существующий код добавив к функции соотвествующий декоратор.

 

Типичный пример:

 

Здесь мы объявили задачу add, которая складывает два аргумента и возвращает сумму. Декоторар shared_task “превращает” функцию в celery задачу. Поэтому у функции появляется метод delay – используя его мы кладем исполнение функции в очередь с указанными аргументами.

 

В нашем GitHub репозитории https://github.com/Glueon/celery_examples мы выложили пару примеров работы с Celery.

 

Помимо кода в репозитории находится docker-compose.yml файл – конфигурация для контейнеров, которые мы используем для запуска тестов.

 

Celery может работать как в синхронном, но мультипоточном режиме, так и в асинхронном с eventlet и gevent. В первом случае Celery запускается с указанным количеством потоков. На каждую задачу занимается свой поток. Если свободных потоков нет задачи ждут очерди, пока какая-либо работающая задача не завершится и не освободит поток.

 

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