我在我的 Symfony 设置中实现了一个命令,它从数据库中获取一个作业,然后处理它。
如何一次运行多个命令实例,以更快地完成作业。我知道 PHP 不支持多线程,但看到命令是从 shell 调用的,我想知道是否有解决方法。
调用命令使用:
app/console job:process
我在我的 Symfony 设置中实现了一个命令,它从数据库中获取一个作业,然后处理它。
如何一次运行多个命令实例,以更快地完成作业。我知道 PHP 不支持多线程,但看到命令是从 shell 调用的,我想知道是否有解决方法。
调用命令使用:
app/console job:process
我解决这个问题的方法是使用一个有多个工作人员的工作队列。它比手动运行多个进程和担心并发更容易管理和扩展。
我发现用于使用 php/symfony 的最简单的通用队列是beanstalkd,您可以使用 LeezyPheanstalkBundle 将其集成到symfony2
我写了一篇关于如何解决这个确切问题的博客文章。https://plume.baucum.me/~/Absolutely/running-multiple-processes-simultaneously-in-a-symfony-command
在这里重新散列所有内容太长了,但基本概念是您的命令可以选择接受作业的 ID。该命令将检查是否提供了 ID。如果没有,那么它将从数据库中获取所有作业,循环它们,并使用作业 ID 参数调用自身。随着每个命令的启动,您将其存储在一个数组中,如果数组太大,您就进入睡眠状态,以进行速率限制。当命令完成时,您将它们从阵列中删除。
当使用作业 ID 运行命令时,它将使用Symfony 的锁组件创建一个锁,这样一个作业就不会被意外地一次处理两次。当作业完成或出错时解锁作业很重要。一旦它有了 ID 和锁,它就会调用你编写的任何代码来实际处理工作。
使用这种技术,我将需要花费数小时才能运行的命令(因为它同步执行每个任务)变成了只需几分钟。确保尝试不同的限制来平衡资源利用率和执行任务所需的时间。
一般来说,我建议使用入队库。您可以从各种可用的传输中进行选择,从最简单的文件系统和 Doctrine DBAL 到真正的一次性传输(例如 RabbitMQ 和 Amazon SQS)。
关于消费者,您需要某种流程管理器。有几种选择:
http://supervisord.org/ - 你需要额外的服务。它必须正确配置。
像这样的纯 PHP 进程管理器。基于 Symfony 进程组件和纯 PHP 代码。它可以处理进程重启、正确退出 sigterm 信号等等。
像这样的 php\swoole 进程管理器。它需要一个 swoole PHP 扩展,但它的性能是惊人的。