Как стать автором
Обновить

Комментарии 22

Я для себя ранее открыл пару аналогичных либ, в некоторых — данная проблема обработки рутинных задач решена:
Dramatiq
Huey

Наследование реализую с помощью механизма pipeline и functools.partial. Увы Celery — не серебряная пуля ;)
P.S.: В данный момент — все чаще использую pika или aiopika.
Большое спасибо, в ближайшее время ознакомлюсь
Ознакомился. В проекте взаимодействуют 2 разных инстанса Celery, каждый со своим изолированным набором тасок. Прямо вот в этом месте dramatiq и huey с их глобальным app становятся непригодными

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

Вообще celery переживает сложный период с выходом 4.x и качество «продукта» упало.
В celery очень много наростов, которые комьюнити видимо не может поддерживать и они просто вырезаются, из наиболее интересных это прекращение поддержки Redis как брокера.
Внутренности celery и его обвязок тоже не сахар (видел, исправлял, пытался доработать) и как это всё стабилизируется непонятно.
Часто обвязки несовместимы друг с другом, в некоторых версиях есть ошибки, а версии без ошибок уже дают ошибки из-за несовместимости.

Слишком сложный продукт стал для простого запуска задач (построение workflow из задач полноценно не работает в celery, дальше chain и group лучше не ходить).

Работаем с celery c 2015 года и через пару недель надеюсь откажемся от него, хотя задач у нас всего 3000-5000 в час.

Версия 3.x была вполне стабильна.
> Странно, что мейнтейнеры согласились включить это в репозиторий

Да вот до сегодняшнего дня там просто висела лычка «Milestone 4.5». Сегодня пол дня рассказывал, что это и зачем это. Пока туго, придётся тестовый проект писать

> уж так ли это необходимо?

У меня есть аналогия — ООП. Дело в том, что без ООП можно реализовать что угодно — сишные структурки в помощь. Однако почему-то ООП является наиболее популярной парадигмой, хотя, казалось бы, так ли это необходимо?

> из наиболее интересных это прекращение поддержки Redis как брокера

Странно, документация говорит, что redis поддерживается в качестве брокера. Можно подробнее?

> Внутренности celery и его обвязок тоже не сахар (видел, исправлял, пытался доработать) и как это всё стабилизируется непонятно.

Да, хорошо видно, что celery писался разными людьми. Одного посещала муза, другого нет
А что вы вкладываете в слово `обвязки`? Модули? Или уровни абстракции?

А вообще celery нужен хороший рефакторинг. Каким образом взаимодействуют пул и хаб я пока не понял, поэтому мой asyncio-пул — это пока скорее костыль, нежели решение.
ООП дело вкуса, просто всего один метод в классе…
Про redis погорячился, это в 2016 году они хотели его почикать, но оставили github.com/celery/celery/commit/e15b0bfc658b397955beeae4a84127cf44686d50

Обвязки это billiard, kombu, beat и т.д.
О, интересная ссылочка

> ООП дело вкуса, просто всего один метод в классе…

Так в том и дело, что не один. Я упираю на множественное наследование. Один (опять же, это слабодостижимый идеал. Чаще несколько) метод требуется до или переопределить и скомбинировать остальные.

Ага, то есть и и модули, и абстракции. Так, а какие претензии к kombu? Свести под одну гребёнку разные шины сообщений — это же прекрасно. А чем billiard провинился? Получилась хорошая абстракция и по факту основа для построения кластера. Beat же вообще опциональный. Для одного воркера можно передать флаг -B — и beat будет встроен в воркер. Естественно, для нескольких экземпляров воркеров нельзя встраивать beat, иначе копии тасок станут исполняться на каждой ноде. Во весело запустить одновременно несколько сессий бэкапа БД.

А вообще к beat у меня персональный пунктик. Вот есть же kombu под капотом. Но нет — расписания мы способны подхватить лишь при старте. Выкручивался пакетом redisbeat, благо, брокером использовался как раз redis. Там кстати смешной баг был. Ну как смешной, стул тогда подо мной прогорел
Естественно, для нескольких экземпляров воркеров нельзя встраивать beat, иначе копии тасок станут исполняться на каждой ноде.

celery-redbeat решает проблему. Просто запускаем все celery с -B и не беспокоимся.


запустить одновременно несколько сессий бэкапа БД

Ну подобные таски в лок оборачивать положено, независимо ни от чего, например с помощью python-redis-lock

celery-redbeat решает проблему

Неа, эту проблему решает просто внешний шедулер, и стандартного хватит. Когда появляется слово «динамика», стандартный шедулер уходит в закат

А за библиотечки спасибо — celery-redbeat выглядит поприятнее, чем redisbeat. python-redis-lock интересен тем, что он идёт в поставке с celery-redbeat
Сколько неприятных моментов нам доставили распределенные блокировки по TTL в случае нештатных ситуаций :)
Самое печально, что блокировки по TTL без отслеживания смерти клиента в случае аварии могут помешать системе восстановиться после простого ребута.

python-redis-lock может ставить лок с TTL и обновлять его, пока процесс работает. Умер/подвис процесс — лок устарел.


with redis_lock.Lock('my-lock', expire=60, auto_renewal=True):
    # Do work....
Это всё до боли знакомо и ясно :)
Но лок устареет только через 60 секунд.
А если у нас длительные процессы с несколько непонятной продолжительностью которые ресурсы берут? Аппроксимация TTL? Обновление TTL? Ну его… не надёжно это всё, всёравно останется какая-то блокировка у которой TTL несколько часов.
Мы своё элегантное решение сделали, пока обкатываем и оформляем, если интересно то пишите asovetnikov на гмейле
По отдельности kombu, billiard и всё остальное прекрасны может быть, но этот зоопарк сильно связан по конкретным версиям между собой и в случае ошибки в одном начинается процесс подбора версий.

Смешно было, когда проект с celery 3.x решили под Python 3.7 запустить. В одной из не самых свежих либ была строка вида import foo.async.bar— получаем SyntaxError :)

Смеяться будете, мы запустили celery 4.2 под Python 3.7 и нам пришлось переименовывать async в asynchronous.

Это в kombu 4.2.0 пофикшено было полтора года назад. Сама селери 4.3.0 стабильная сейчас. Собственно, в вышеупомянутом проект бампнули селери до 4.3.0 и никаких проблем.

Вы будете смеяться дальше, но нам пока некогда и нет смысла переходить дальше Django 1.8, а celery 4.3 не дружит если у тебя ниже 1.9
Потрясающая зависимость celery и Django :)
Заниматься этим всем и ждать новых сюрпризов смысла не вижу, есть положительный опыт с другой библиотекой, проще перейти.
Уж до кучи, забыл совсем — flower крайне негативные эмоции вызывает, история задач вечно куда-то теряется, фильтровать нормально нельзя, какие-то пустые поля в задачах часто бывают, чувство потери контроля в сравнении со старым celery cam и djcelery
А почему вы не воспользовались тем, что «таска» в Celery — это на самом деле и есть класс, который налету создаётся декоратором app.task() с использованием базового класса celery.Task? С давних пор можно было самому писать «таски» в виде классов унаследованных от celery.Task.
Минус был только в том, что их не так удобно регистрировать в Celery-приложении, как это делается с декоратором. И ещё в минус можно записать невозможность переопределить базовый класс через настройку Celery.
Хороший вопрос. Действительно, можно указать базовый класс для таска. Проблема однако в том, что:
  1. Проблему бойлерплейта он не решает
  2. Я боялся нарваться на коллизию имён. Хотелось отделить логику задачи от логики celery
  3. Минусы вы назвали сами. Частно говоря, вы их назвали больше, чем я знал
  4. И вкусное: а мой подход не запрещает их комбинировать
Никто не мешает написать свой «базовый» класс на основе оригинального, что бы спрятать в него бойлерплейт. Я так и сделал — запихал туда обработку ошибок, логирование и хитрую инициализацию энвайромента.

Хотя… вот вам самый важный «минус» — экземпляр класс-таски в Celery создаётся только один, и потому его нельзя использовать для хранения данных выполняемой таски. Для этого можно использовать «словарик» Task.request — он создаётся каждый раз перед запуском таски.
Ох, точно, это и была та самая причина, по которой я отбросил затею с классами Task. Знатно подо мной тогда стул прогорел — а в чём смысл класса?

А обработку ошибок я в примерах и предложил направить в метод task. Разве что всё под рукой — в базовом классе, а не снаружи
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории