Самым популярным паттерном проектирования классов безусловно был и остаётся Singleton — паттерн, который гарантирует уникальность объекта класса в рамках одного процесса.
Но что если возникает необходимость унифицировать сам процесс? В этой статье пойдёт речь о том, в каких задачах это может понадобиться и как этого добиться.
Введение
Есть ряд задач, в которых принципиально важно, чтобы определённый скрипт выполнялся исключительно в единственном варианте т.к. параллельный запуск его несколькими процессами может привести к различного рода накладкам.Примеров тому можно найти много, но по большей части это будут различного рода фоновые обработчики, как то: фоновые рассыльщики email / sms, утилизаторы кэша, мониторинг активных пользователей, фоновый бэкап и т.п.
Два способа реализации
Есть два основных способа реализации таких задач:- Писать скрипты, которые будут исключать все возможные накладки их параллельного запуска.
- Использовать систему контроля уникальности запуска скрипта.
ScriptAlone — «контроллер» уникальности процесса
ScriptAlone представляет из себя класс, объекты которого служат «контроллерами» уникальности процесса. Он был неоднократно оптимизирован и доработан, а также на 100% протестирован в боевых условиях, так что я могу с уверенностью рекомендовать вам его использование.Дабы не быть многословным расписывая все его прелести предлагаю познакомиться с тем как он работает на конкретном примере.
Пример
У вас есть живая очередь писем которые должны стабильно оправляться в кратчайшие сроки.Требования
- Необходим скрипт, который будет постоянно запущен и каждую секунду проверять наличие в очереди писем на отправку.
- Может быть запущена только одна копия скрипта, чтобы исключить ситуации дублированной отправки писем.
- Если работа скрипта прерывается из-за ошибки, то он должен быть перезапущен как можно скорее.
- Если скрипт подвисает на выполнении одной из итераций, то он должен быть перезапущен как можно скорее.
- Скрипт должен перезапускаться каждые 5-10 часов, чтобы предотвратить возможные утечки памяти. Остановка скрипта в этом случае должна производиться безопасным образом (когда задачи текущей итерации выполнены).
- Необходимо некий индикатор того, что скрипт в данный момент запущен
- Необходимо наличие возможности принудительно остановить выполнение скрипта.
Что необходимо сделать
- Взять example.php — простенький скрипт использующий ScriptAlone.
- Настроить CRON на вашем сервере таким образом, чтобы example.php вызывался каждые 5 минут.
Что получится
- Скрипт будет постоянно запущен. Проверка наличия новых писем будет производиться каждую секунду.
- В любой момент времени будет запущена только одна копия скрипта.
- Если работа скрипта прервётся или лимит времени на выполнение одной итерации будет исчерпан, то скрипт будет перезапущен.
- Каждые 5 часов скрипт будет перезапускаться безопасным образом.
- Перезагрузка скрипта подразумевает его повторный запуск не позднее чем через 5 минут после остановки — это обусловлено настройкой CRON-а на попытку запустить очередную копию скрипта каждые 5 минут.
- Убедиться в том, что скрипт в данный момент запущен можно по наличию файла ./example.php.works. Также из его содержимого можно почерпнуть дополнительную информацию о статусе работы скрипта:
PID: 12656471471193231407
Started: 2010-02-08 19:39:07
Worked: 2010-02-08 19:39:10
Expire: 2010-02-08 19:39:26
- Остановить выполнение скрипта можно просто создав файл с именем ./example.php.works.stop
Пользуйтесь на здоровье :)
Скачать последнюю версию, подписаться на обновления по RSS или поучаствовать в разработке можно на странице проекта.
Спасибо заранее за конструктивную критику и отзывы :)
P.S. В процессе написания статьи было выявлено странное поведение хабра: все слова начинающиеся на Script* переводятся в нижний регистр — исправляется самостоятельной заменой Script на Script. Все ссылки, в которых встречается *script* заменяются на *script* что делает их нерабочими — исправляется самостоятельной заменой *script* на *s%63ript*. Отписался в саппорт, но пока не ответили.