2014-01-27 2 views
1

Предположим, у меня есть код 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-daemonlike 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 и отложить перезапуск скрипта до текущей задачей является обработка.

+1

Вы не уверены в использовании транзакций для несогласованности данных в базе данных? –

+0

Ах, я просто понял, что могу использовать транзакции для этого, так как я использую MySQL. Хорошая идея, на самом деле. –

+1

Вы также можете подключить SQS к SNS и сделать SNS ping HTTP-запрос конечной точке каждый раз, когда появляется новое сообщение. Он также обеспечивает экспоненциальное падение, и я использовал его довольно успешно. Я также пробовал PHP-демоны, и они довольно нестабильны и протекают (PHP на самом деле не предназначен для этого). Дайте мне знать, если вам нужна дополнительная информация, и я отправлю ответ, если так. – andreimarinescu

ответ

1

Возможно, следующее поможет вам. Я закодировал это некоторое время назад, но все еще использую его в некоторых проектах.

PHP Process Management classes

Usage example (pm.php and sleep.php) - статья на русском языке, но вы получите идею с помощью Google Translate

Эти классы позволяют вам установить связь между первичными сценариев и задач сценариев; так что вы можете реализовать какой-то перезапуск функциональность - сценарий задачи выполнит изящную остановку при получении сигнала перезагрузки, тогда основной скрипт снова запустит задачу

Не стесняйтесь задавать вопрос о коде.

0

Я искал документ AWS, который добавляет подписку SQS на тему SNS, к сожалению, я не могу найти ее прямо сейчас. Общая архитектура заключается в том, что вы подписываете как свою конечную точку HTTP, так и очередь SQS на тему SNS. Затем вы можете опубликовать сообщение SNS всякий раз, когда вам нужно обработать задание, причем детали задания каким-то образом сериализованы в теле сообщения. Когда конечная точка HTTP получает новое сообщение SNS, он может затем опросить очередь для нового сообщения, получить данные сообщения и обработать задание. Затем он может удалить сообщение из очереди. Таким образом, я думаю, что вы даже можете обойти аутентификацию сообщения SNS, поскольку вы собираетесь использовать обратный вызов SNS для вызова вашего PHP-скрипта, а данные задания надежно сохраняются в SQS.

Что касается демонализации PHP, я смотрю на это примерно 3-4 года назад. В то время это было очень непрозрачное и неустойчивое решение, с тех пор все могло измениться. В то время я занимался созданием очень простого демона Python (просто для того, чтобы развернуть процесс в основном), который вызвал мой PHP-скрипт через PHP CLI каждые X секунд. Вы можете даже многопоточно это и запустить более одного PHP-скрипта или сократить интервал, в зависимости от ваших потребностей масштабирования и мощности вашего сервера. Один приятный эффект заключается в том, что вам не нужно беспокоиться о многопоточности в PHP.

Надеюсь, это немного поможет, сообщите мне, как я могу предоставить дополнительную информацию в комментариях, если это необходимо.

Смежные вопросы