Предположим, у меня есть код PHP, который потребляет из очереди сообщений и запускает некоторый класс в соответствии с сообщением.Безопасное обновление кода PHP, выполняющегося навсегда. Для обработки очереди
#/usr/bin/env php
//pseudo php code
while(true){
$message = $queue->getMessage();
$content = json_decode($message->content);
switch($content->type){
case 'a':
runFunctionA($content->data);
break;
case 'b':
runFunctionB($content->data);
break;
case 'c':
runFunctionC($content->data);
break;
}
$message->delete();
}
Это мой первый опыт использования очереди сообщений. Поскольку я уже на вершине AWS, я собираюсь попробовать использовать AWS SQS. Я думаю, что это будет намного проще, так как мне не нужно развернуть сервер очереди с нуля.
Моя первая проблема заключается в том, как убедиться, что процесс запустится снова, если, например, в runFunctionA
произошла ошибка, вызывающая остановку скрипта. Но после поиска через StackOverflow я нашел эту тему 'Have a PHP script run forever, access a queue' и 'How can I keep an Amazon SQS PHP reciever script running forever?'. В основном у меня возникла идея создать cronjob для проверки файла блокировки. Из моего опыта написания сценариев оболочки я могу достичь этого, используя start-stop-daemon
like this. (1) Или есть лучший или более распространенный способ?
Но теперь я все еще не могу понять, как безопасно обновлять код, например, когда я хочу обновить содержимое runFunctionA
. В настоящее время я планирую, чтобы задачи с очередью были в одной и той же базе кода с веб-сайтом, поскольку большая часть бизнес-логики уже реализована там.
Мой текущий механизм развертывания - это сохранение zip-кода на веб-серверы и изменение ссылки на новый код. Что-то вроде ниже.
wget http://path/to/code.zip -O /path/to/temp/dir
rm /var/www
ln -s /path/to/temp/dir /var/www
#Let's say the forever loop is in script /var/www/queue_consume.php
Поскольку HTTP запросы коротки, я думаю, что развертывание с помощью этого механизма является довольно безопасным (и я думаю, что это наиболее распространенный способ). Но я не уверен в обновлении долгого PHP-кода.
Мой главный вопрос: (2) Как сделать вечную петлю безопасным использованием вновь развернутого кода runFunctionA
? Поскольку у меня уже есть идея с использованием start-stop-daemon
выше, я могу в принципе перезапустить демона. Но опять же, (3) есть еще один распространенный способ сделать это. И, наконец, (4) как обеспечить, чтобы цикл, по крайней мере, завершил выполнение задачи до обновления кода? Моя основная забота - это о согласованности данных в задаче. Если сценарий PHP перезапускается принудительно, в базе данных может быть несогласованность.
UPDATE
До сих пор единственная идея, у меня есть, чтобы отделить цикл и задачу. В цикле я могу сделать exec
, например,
#/usr/bin/env php
//pseudo php code
while(true){
$message = $queue->getMessage();
$return = 1;
$output = '';
exec("/var/www/tasks.php {$message}", $output, $return);
if ($return == 0)
$message->delete();
}
Что касается консистенции, я имею в виду использовать PHP Process Control, чтобы поймать сигнал, посланный Deployer и отложить перезапуск скрипта до текущей задачей является обработка.
Вы не уверены в использовании транзакций для несогласованности данных в базе данных? –
Ах, я просто понял, что могу использовать транзакции для этого, так как я использую MySQL. Хорошая идея, на самом деле. –
Вы также можете подключить SQS к SNS и сделать SNS ping HTTP-запрос конечной точке каждый раз, когда появляется новое сообщение. Он также обеспечивает экспоненциальное падение, и я использовал его довольно успешно. Я также пробовал PHP-демоны, и они довольно нестабильны и протекают (PHP на самом деле не предназначен для этого). Дайте мне знать, если вам нужна дополнительная информация, и я отправлю ответ, если так. – andreimarinescu