执行长时间运行的PHP脚本的最佳实践

执行长时间运行的PHP脚本的最佳实践,php,laravel,symfony,magento,cron,Php,Laravel,Symfony,Magento,Cron,我们需要分发包含PHP脚本的软件,该脚本将运行几分钟。因此,我正在寻找在2017年实现这一目标的最佳实践方式 它必须由HTTP请求调用。应该没有HTTP请求等待几分钟,因此在访问者得到HTTP响应后,脚本必须静止运行 它必须定期运行(每晚)。它还应该按照默认值每晚运行(如cron作业)。注意:由于软件将分发给客户端,因此我们无法手动添加cronjob(我们无法访问客户端服务器)。一切都应该在PHP代码中完成 (请注意,我自己也阅读了现有的博客文章和问题,但我找不到令人满意的答案) 也许有人

我们需要分发包含PHP脚本的软件,该脚本将运行几分钟。因此,我正在寻找在2017年实现这一目标的最佳实践方式

  • 它必须由HTTP请求调用。应该没有HTTP请求等待几分钟,因此在访问者得到HTTP响应后,脚本必须静止运行
  • 它必须定期运行(每晚)。它还应该按照默认值每晚运行(如cron作业)。注意:由于软件将分发给客户端,因此我们无法手动添加cronjob(我们无法访问客户端服务器)。一切都应该在PHP代码中完成

(请注意,我自己也阅读了现有的博客文章和问题,但我找不到令人满意的答案)

也许有人知道像Symfony和Laravel这样的框架或者像Magento这样的webshop是如何完成这些任务的?不过,我还是想知道如何在不使用框架或库的情况下在普通PHP中自己完成这项工作。

存在许多解决方案:

  • 使用exec(相当不安全),这会触发后台作业(在评论中建议,我可能更喜欢symfony进程,但仍然不安全)
  • 使用cron每隔一段时间触发一个symfony进程,而不是通过http,这样更安全
  • 使用php fpm,您可以使用
  • 使用队列系统(SQS、RabbitMQ、Kafka等)
  • 使用
  • 使用守护进程和类似supervisord的东西来确保它连续运行
最好的解决方案肯定是队列和cron,然后是PHP-FPM,其余的都是垃圾

如果不做一些在某一点上不起作用的事情,你绝对不可能在别人的服务器上运行

旁注:你说你不想要库是为了知道如何自己做,我添加了到库的链接,因为阅读它们可以让你对技术有更深入的了解,这些库的质量非常高。

存在许多解决方案:

  • 使用exec(相当不安全),这会触发后台作业(在评论中建议,我可能更喜欢symfony进程,但仍然不安全)
  • 使用cron每隔一段时间触发一个symfony进程,而不是通过http,这样更安全
  • 使用php fpm,您可以使用
  • 使用队列系统(SQS、RabbitMQ、Kafka等)
  • 使用
  • 使用守护进程和类似supervisord的东西来确保它连续运行
最好的解决方案肯定是队列和cron,然后是PHP-FPM,其余的都是垃圾

如果不做一些在某一点上不起作用的事情,你绝对不可能在别人的服务器上运行


旁注:你说你不想要库是为了知道如何自己做,我添加了到库的链接,因为阅读它们可以让你对技术有更深的了解,这些库的质量非常高。

如果你为Magento设置常规的cronjob,Magento只运行它的cronjobs。它有一个cron.sh,每分钟运行一次,并执行Magento队列中的作业


任何通过http执行长时间运行任务的解决方案都涉及web服务器配置。

如果为Magento设置常规的cronjob,则Magento仅运行它的cronjobs。它有一个cron.sh,每分钟运行一次,并执行Magento队列中的作业


任何通过http执行长时间运行任务的解决方案都涉及web服务器配置。

最后,我认为有两种方法可以通过http请求启动PHP中的长时间运行进程(而不让用户等待很长时间):

  • 使用FPM,并使用将响应发送给用户。发送响应后,您可以执行任何您想要的操作,例如长时间运行的任务。(这里您不必启动新流程,只需继续使用PHP即可)

  • 使用以下函数之一创建新流程。将STDOUT和STDERR重定向为null并将其置于后台(您必须同时执行这两项操作)。为了仍然获得新进程的输出,新进程可以写入一些日志文件

    exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    shell_exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    system('php longrunningtask.php >/dev/null 2>/dev/null &');
    passthru('php longrunningtask.php >/dev/null 2>/dev/null &');
    
    或者像
    symfony/process
    那样使用
    proc\u open()


注:

  • symfony/process
    :在文档中,您可以看到,对于长时间运行的任务,您可以使用FPM和
    fastcgi\u finish\u request()
  • 安全性:我看不出有内置的安全风险,你只需要做正确的事情,然后一切都会好起来(你可以使用密码保护,验证你的命令的可能输入,等等)
  • 对于cron作业,问题的一部分没有答案。我认为这是不可能的

最后,我认为有两种方法可以通过HTTP请求启动PHP中的长时间运行进程(而不让用户等待很长时间):

  • 使用FPM,并使用将响应发送给用户。发送响应后,您可以执行任何您想要的操作,例如长时间运行的任务。(这里您不必启动新流程,只需继续使用PHP即可)

  • 使用以下函数之一创建新流程。将STDOUT和STDERR重定向为null并将其置于后台(您必须同时执行这两项操作)。为了仍然获得新进程的输出,新进程可以写入一些日志文件

    exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    shell_exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    system('php longrunningtask.php >/dev/null 2>/dev/null &');
    passthru('php longrunningtask.php >/dev/null 2>/dev/null &');
    
    或者像
    symfony/process
    那样使用
    proc\u open()


注:

  • symfony/process
    :在文档中,您可以看到,对于长时间运行的任务,您可以使用FPM和
    fastcgi\u finish\u request()
  • 安全性:我看不出有内置的安全风险,你只需要做正确的事情,然后一切都会好起来(你可以使用密码保护,验证你的命令的可能输入,等等)
  • 对于cron作业,问题的一部分没有答案。我认为这是不可能的