Cron-задания часто являются одной из составляющих долгоживущего сервиса.
Могут применяться как сборщики мусора. Или как инициаторы заданий для воркеров.
Проблематика
В большой распределённой системе cron-задания могут быть не рассчитаны на параллельную работу. Например, не реализовывать протокол Paxos
Поэтому требуется реализовать блокировку от параллельного выполнения.
Но начнём мы с часто совершаемой ошибки при полном цикле разработки и эксплуатации в разных отделах
cron находится в отличном от кода репо / настраивается вручную по заявке
Предположу, что есть варианты, когда срок горит, а разбираться в CI/DevOps практиках лень.
Тогда долгосрочной эксплуатации продукта отдаётся меньший приоритет, чем быстрому запуску.
Как следствие - cron настраивается инженерами экплуатации в системе, к которой программистам доступа нет.
Для грамотной разработки и поддержки важно понимать, как работает проект сейчас (в общем случае в конкретный момент времени).
А так как cron - часть проекта, его работа должна быть понятной для всех (разработчиков, эксплуатации и т.д.).
Поэтому вывод
Cron должен быть реализован в проекте
Основные агурменты за:
- конфигурация на виду у всех членов команды, а не записана в блокноте у уволенного сотрудника;
- имеется возможность протестировать и внести изменения вместе с изменениями проекта;
Реализация
Обычно вызов cron операций бывает:
- асинхронным вызовом через сеть (веб-сервер или другой сигнал для запуска команды);
- этот путь не даёт контроля над результатом выполнения cron-операции;
- возможен, если это постановка задания в очередь, а не выполнение самого задания.
- можно воспользоваться готовым образом https://hub.docker.com/r/renskiy/cron/
- вызовом операции в самом приложении
- контроль исполнения;
- контроль ресурсов;
- получаем точный код и трассировку в случае ошибки.
Ограничения
В распределённой системе нужно котролировать параллельный запуск, если возможны ошибки при параллельном выполнении двух cron-заданий.
Блокировка от параллельного выполнения
#!/bin/bash
PROCNUM=`ps xa | grep -v grep | grep -c "/srv/www/data/cron.php"`
# если процесс уже есть - выходим
if [ $PROCNUM -gt 0 ]; then exit; fi
/usr/local/bin/php /srv/www/data/cron.php
Обработка ошибок
Сообщения, которые затем должны быть видны в системе логирования, стоит записать в лог контейнера. Система логирования автоматически их обработает и отдаст в удобном для клиента виде.
Соответствует методике 12 факторов