Pull to refresh

Comments 17

Ну, в принципе, конечно, для новичков будет ОК. Но от себя добавлю что нужно понимать - celery - это очень сложный и громоздкий комбайн, который сильно связан с несколькими другими библиотеками того же автора (kombu, amqplib, billiard?). Проекту уже больше 10 лет и внутри всех этих библиотек просто кошмар что творится - для поддержки разных фич, сериализаторов и движков там накручено очень много сложного кода.

Если вы ставите celery на продакшен - вы должны быть хорошим специалистом по нему. Это вопрос времени когда вы начнете узнавать очень интересные вещи про таймауты и потоки, пропадающие задачи и забитые очереди.

Celery крут, но я бы советовал новичкам взять что-то менее тяжелое для своих новичковых задач.

FastStream больше заточен на фичи брокера, чем на "сам себе брокер", так что отлично подойдет для изучения MQ концепций. Да и в половине кейсов вам именно этот функционал нужен, а не Celery.

https://github.com/airtai/faststream

В качестве примера хранилища очереди у вас используется redis. Почему не keydb?

Простите, я не автор но отвечу вам.

Во-первых, Redis и keydb реализуют совместимый протокол, причем keydb появился сильно позднее Redis. Вряд ли в этой статье стоит вдаваться в их сравнение.

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

Redis, впрочем, очень удобен как results backend - хранить результаты выполнения тасков.

На мой взгляд RabbitMQ и Redis взаимонезаменяемы. Redis больше подходит для задач, где важна скорость и не важна надежность.
Понимаю,что статья учебная и не так важно, какой инструмент в ней приводится. Но подобные статьи могут служить так же и популяризацией инструментов. В этом смысле я бы сказал, что redis и так достаточно популярен и на слуху, в отличие от keydb, который достоен популяризации.

На мой взгляд RabbitMQ и Redis взаимонезаменяемы. Redis больше подходит для задач, где важна скорость и не важна надежность.

Здесь можно поспорить. Насчет надежности - да, это одно из отличий. Redis может потерять задачу, например. Однако, встроенные "очереди задач" в Redis - это немного усложнённые списки с простейшим Pub/Sub. Ни подтверждений, ни блокировок.

RabbitMQ с AMQP протоколом предоставляет гораздо больше механизмов для маршрутизации. prefetch, late_ack, приоритеты, повторы, бродкаст, блокировки на время выполнения - ничего из этого нет в Redis, а приделывается программно в коде клиента. RabbitMQ давно масштабируется в кластер штатно, а в однопоточном Redis с этим раньше были проблемы (не знаю как в keydb).

Автор celery (Ask Solem) довольно долго работал в VMWare как раз в то время когда они купили (ок, инвестировали в) RabbitMQ. Можно утверждать что celery построен специально для AMQP, а все остальные движки были приделаны уже для совместимости.

Для прототипов или локально я сам использую Redis в качестве брокера, если не нужна ручная маршрутизация - проще обслуживать. Но для продакшена - точно не буду.

у RabbitMQ есть фатальный недостаток: авторы в issue на Github не рекомендуют запускать его в Kubernetes из-за нежности встроенной базы данных, а просто подключить внешний PostgreSQL/MySQL нельзя. И в облаках особо не продаётся Managed RabbitMQ. Поэтому если можно жить на Redis, каковой лишён этого недостатка, или можно просто начать использовать Kafka вместо RabbitMQ, то всё выглядит так, что лучше так и поступить.

Не исключено, что это совсем неверное впечатление, но когда мне это потребовалось при миграции Django-приложения с Celery с VM в Kubernetes, то оказалось что у RabbitMQ как-то не очень с массовыми современными материалами по HA RabbitMQ и его Disaster Recovery.

Моё впечатление неверно?

Боюсь что я вам ничего не могу расказать про жизнь сервисов в кубернетесе, поскольку не сталкивался с этим для RabbitMQ. Однако, он, действительно, не любит когда сервера в кластере меняются. Встроенная база (Mnesia), на мой взгляд, не должна сильно отличаться по требованиям к диску от любой другой базы.

Спасибо за замечание, сделаю себе в уме пометку про RabbitMQ/k8s.

Есть протокол для взаимодействия с очередью, AMQP, он открытый. RabbitMQ - одна из реализаций очереди, и общение с ним происходит по этому протоколу. Есть несколько других реализаций очередей, совместимых с этим протоколом, продающихся как SaaS. Кроме того, в библиотеке kombu, которую использует Celery, есть возможность использовать некоторые реализации очередей с их нативными протоколами. Это в общих чертах, но конечно же везде есть свои нюансы

но хотят-то именно продукт RabbitMQ со всеми его фичами, интерфейсом и экспортерами, а не просто протокол подключения

Можно ли стандартными средствами celery как то реализовать очередь для каждого пользователя? Вот пример: возьмём приложения на flask. Пользователь делает запрос например на генерацию отчета, создается задача в celery. Она возвращает статус что выполняется и пользователь может с интервалом запрашивать статус задачи. Так же пользователь может запросить другой отчет. Но нужно сделать так что бы вызов второй задачи произошло только после завершения первой.

Сейчас у меня реализовано это своим велосипедом с очередями и дополнительной задачей, которая стартует по расписанию и запускает задачи для пользователя, если нет активных на этот момент.

Конечно можно, через canvas. в вашем случае - это будет chain.

и пользователь может с интервалом запрашивать статус задачи

Это не очень рекомендуемый способ. Правильный способ - использовать коллбэки или другие таски. То есть, ваша таска завершилась и вызвала какой-то другой механизм для оповещения пользователя.

Опрос celery через его API - довольно непростая задача. К примеру, получите вы статус PENDING, но он может иметь много смыслов. Например, это таска, которая ждёт своей очереди для выполнения. Однако, это же вернётся для неизвестной таски или (!) для уже выполненной таски если время хранения её результатов истекло или не было предусмотрено (ignore_result=True)

спасибо! Но chain же можно использовать, если задачи известны заранее, Но к уже запущенной нельзя же добавить следующую задачу?

Это не очень рекомендуемый способ. Правильный способ - использовать коллбэки или другие таски. То есть, ваша таска завершилась и вызвала какой-то другой механизм для оповещения пользователя.

Да, так и делается, я не к самому celery обращаюсь, а к внешнему apiб который проверят статус задачи в БД.

А, теперь понял что вы хотите сделать. Сначала я хотел написать что так сделать не получится, но пошёл в документацию и вижу флаг add_to_parent для метода apply_async. Возможно, это то что вам нужно.

имхо еще осталось ‘myapp/__init__.py’ дописать

Sign up to leave a comment.