Работать вокруг celerybeat является единственной точкой отказа

Я ищу рекомендуемое решение для работы с celerybeat, являющееся единственной точкой отказа для внедрения сельдерея/кролика. Я не нашел ничего, что имело смысл до сих пор, путем поиска в Интернете.

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

Я надеюсь, что для этого уже есть рабочее решение, поскольку я не могу быть единственным, кому нужен надежный (сгруппированный или похожий) планировщик. Я не хочу прибегать к какому-то планировщику с поддержкой базы данных, если мне это не нужно.

Ответы

Ответ 1

В реестре сельдерея github есть открытая проблема об этом. Не знаю, работают ли они на этом.

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

Что-то вроде:

if not cache.add('My-unique-lock-name', True, timeout=lock_timeout):
    return

Вывод таймаута блокировки - это хорошо, сложно. Мы используем 0.9 * task run_every seconds, если разные celerybeat будут пытаться запускать их в разное время. 0.9, чтобы оставить некоторый запас (например, когда сельдерей немного отстает от графика один раз, то он по расписанию, который заставит блокировку оставаться активным).

Затем вы можете использовать экземпляр celerybeat на всех машинах. Каждая задача будет поставлена ​​в очередь для каждого экземпляра celerybeat, но только одна из них завершит прогон.

Задачи будут по-прежнему уважать run_every этот путь - наихудший сценарий: задачи будут выполняться со скоростью 0.9 * run_every.

Одна проблема с этим случаем: если задачи были поставлены в очередь, но не обрабатывались в запланированное время (например, потому, что очереди процессоров были недоступны), тогда блокировка может быть помещена в неподходящее время, что может привести к тому, что одна следующая задача просто не будет выполняться. Чтобы обойти это, вам понадобится какой-то механизм обнаружения, будет ли задача более или менее своевременной.

Тем не менее, это не должно быть обычной ситуацией при использовании в производстве.

Другим решением является подкласс celerybeat Scheduler и переопределение его метода тика. Затем для каждого тика добавьте блокировку перед обработкой задач. Это гарантирует, что только celerybeat с такими же периодическими задачами не будет ставить в очередь одни и те же задачи несколько раз. Только один выбор celery для каждого тика (тот, кто выигрывает условие гонки) поставит в очередь задачи. В одном сельдеревом мясе спускается, а следующий тик другой выиграет гонку.

Это, конечно, можно использовать в сочетании с первым решением.

Конечно, для этого для работы необходимо, чтобы бэкэнд кеша должен был реплицироваться и/или использоваться для всех серверов.

Это старый вопрос, но я надеюсь, что это поможет кому-то.