Остановка gearman рабочие приятно

У меня есть много рабочих Gearman, работающих постоянно, сохраняя вещи как записи пользовательских просмотров страницы, и т.д. Иногда, я обновлю код PHP, который используется рабочими Gearman. Чтобы заставить рабочих переключаться на новый код, я уничтожение и перезапускать процессы PHP для рабочих.

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

Править: Я нашел ответ, который работает на меня и отправил его ниже.

43
задан Karptonite 9 June 2010 в 19:35
поделиться

7 ответов

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

Если вы посмотрите код Net_Gearman_Worker, вы обнаружите, что в рабочем цикле отслеживается функция stopWork, и если она возвращает true, она выходит из функции.

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

Я расширил класс Worker до Net_Gearman_Worker_Foo, и все мои рабочие инстанциировали его. В классе Foo я переопределил функцию stopWork, чтобы сделать следующее: во-первых, она проверяет gearman_restarttime; в первый раз он сохраняет значение в глобальной переменной. С этого момента каждый раз он сравнивает кешированное значение с глобальным. Если он изменился, stopWork возвращает true, и рабочий завершает работу. Cron каждую минуту проверяет, работает ли каждый рабочий процесс, и перезапускает любой завершившийся рабочий процесс.

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

7
ответ дан 26 November 2019 в 23:10
поделиться

Это хорошо впишется в вашу систему непрерывной интеграции. Я надеюсь, что он у вас есть, или он у вас скоро появится: -)

Когда вы регистрируете новый код, он автоматически создается и развертывается на сервере. В рамках сценария сборки вы убиваете всех воркеров и запускаете новые.

0
ответ дан 26 November 2019 в 23:10
поделиться

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

Другим способом может быть реализация какого-то прерывания, возможно, по сети, чтобы сказать: "Остановись, когда у тебя есть возможность, и перезапустись".

Последнее решение - помочь модифицировать исходники Gearman'а, чтобы включить эту функциональность.

1
ответ дан 26 November 2019 в 23:10
поделиться

http://phpscaling.com/2009/06/23/doing-the-work-elsewhere-sidebar-running-the-worker/

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

1
ответ дан 26 November 2019 в 23:10
поделиться

Решение 1


Обычно я запускаю свои рабочие процессы с помощью утилиты unix daemon с флагом -r и позволяю им истечь после одного задания. Ваш скрипт будет корректно завершаться после каждой итерации, и демон автоматически перезапустится.

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

Это решение также имеет то преимущество, что освобождает память. У вас могут возникнуть проблемы с памятью, если вы выполняете большую работу, поскольку в PHP до 5.3 есть ужасный сборщик мусора.

Решение 2


Вы также можете добавить ко всем вашим воркерам функцию выхода, которая выходит из скрипта. Когда вы хотите перезапустить, вы просто даете команду gearman выйти с высоким приоритетом.

12
ответ дан 26 November 2019 в 23:10
поделиться

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

Моя первая попытка заключалась в том, чтобы рабочий следил за тем, как давно он в последний раз проверял версию рабочего скрипта (md5sum также подойдет). Затем по прошествии N секунд между заданиями он проверяет, доступна ли новая версия самого себя, и перезапускает себя (fork () / exec ()). Это действительно сработало, но работники, зарегистрированные на редкие вакансии, потенциально могут в течение нескольких часов ждать, пока work () вернется, и, следовательно, для проверки текущего времени.

Теперь я устанавливаю довольно короткий тайм-аут при ожидании заданий с помощью work (), чтобы я мог проверять время более регулярно. Интерфейс PHP предполагает, что вы можете установить это значение тайм-аута при регистрации для работы. Я использую SIGALRM для запуска проверки новой версии. Интерфейс perl блокирует работу (), поэтому изначально тревога не срабатывала. Установка тайм-аута на 60 секунд заставила SIGALRM работать.

1
ответ дан 26 November 2019 в 23:10
поделиться

Если кто-то искал ответ для рабочего, использующего Perl, это часть того, для чего предназначена библиотека GearmanX :: Starter . Вы можете остановить рабочие процессы после завершения текущего задания двумя разными способами: извне, отправив рабочему процессу сообщение SIGTERM, или программно, установив глобальную переменную.

1
ответ дан 26 November 2019 в 23:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: