假设我有一个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来检查一个锁文件。根据我编写shell脚本的经验,我可以使用start-stop-daemon
like this实现此目的。 (1)或者有更好或更常见的方式?
但是现在我仍然无法弄清楚如何安全地更新代码,例如,当我想要更新runFunctionA
的内容时。目前我正计划将排队的任务与网站放在同一个代码库中,因为大部分业务逻辑已在那里实现。
我目前的部署机制是将压缩代码存储到Web服务器中,并将链接更改为新代码。像下面的东西。
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脚本,则数据库中可能存在不一致。
更新
到目前为止,我唯一的想法是分离循环和任务。在循环中,我可以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来捕获部署者发送的信号,并延迟脚本重启,直到当前任务正在处理。
答案 0 :(得分:1)
也许以下内容会对您有所帮助。我刚刚编写了这个,但仍然在一些项目中使用它。
PHP Process Management classes
Usage example (pm.php and sleep.php) - 文章是俄语,但你会通过谷歌翻译得到这个想法
这些类允许您设置主脚本和任务脚本之间的通信;所以你可以实现某种重启功能 - 任务脚本会在收到重启信号时执行正常停止,然后主脚本会再次启动任务
随意询问有关代码的问题。
答案 1 :(得分:0)
我一直在搜索有关向SNS主题添加SQS订阅详情的AWS文档,遗憾的是我现在似乎无法找到它。通用体系结构是您将HTTP端点和SQS队列都订阅到SNS主题。然后,您可以在需要处理作业时发布SNS消息,并在消息正文中以某种方式序列化作业详细信息。 当HTTP端点收到新的SNS消息时,它可以轮询队列以获取新消息,检索消息详细信息并处理该作业。然后它可以从队列中删除该消息。通过这种方式,我认为您甚至可以绕过SNS消息的身份验证,因为您只会使用SNS回调来调用您的PHP脚本,并且作业详细信息会安全地存储在SQS中。
关于守护PHP,我在大约3 - 4年前看过这个。那时候这是一个非常漏洞和不稳定的解决方案,从那以后事情可能会发生变化。我当时所要的是创建一个非常简单的Python守护进程(基本上只是分支进程),每隔X秒就通过PHP CLI调用我的PHP脚本。然后,您甚至可以多线程并启动多个PHP脚本或缩短间隔,具体取决于您的扩展需求和服务器功率。一个很好的效果是你不必担心PHP中的多线程。
希望这有点帮助,如果需要,请告诉我如何在评论中提供其他信息。