问题描述
|
我目前正在尝试在PHP中实现作业队列。然后,该队列将作为批处理作业处理,并且应该能够并行处理某些作业。
我已经进行了一些研究,找到了实现它的几种方法,但是我并没有真正意识到它们的优缺点。
例如。通过多次通过
fsockopen
调用脚本来进行并行处理,如下所示:
在PHP中轻松进行并行处理
我发现的另一种方法是使用curl_multi
函数。
curl_multi_exec PHP文档
但是我认为这两种方式会增加很多开销,这些开销主要应在后台运行,以在队列上创建批处理。
我还读到了大约2英镑,这似乎也是解决该问题的一种方法。但是,如果您真的不知道自己在做什么(好像现在是我),那看起来就会变得很混乱。
我也看过Gearman
,但是我还需要根据需要动态产生工作线程,而不仅仅是运行几个线程,然后让Gearman作业服务器将其发送给自由工作人员。尤其是因为执行完一项作业后应干净退出线程,以免最终导致内存泄漏(在该问题中代码可能并不完美)。
Gearman入门
所以我的问题是,如何处理PHP中的并行处理?为何选择您的方法,不同的方法可能有哪些优点/缺点?
感谢您的任何投入。
解决方法
我用
exec()
。它容易清洁。基本上,您需要构建一个可以满足您需求的线程管理器和线程脚本。
我不喜欢“ 5”,因为它会打开服务器连接,这将建立并可能达到apache的连接限制
出于同样的原因,我不喜欢curl
函数
我不喜欢pnctl
,因为它需要可用的pnctl扩展名,并且您必须跟踪父子关系。
从来没有和齿轮手玩过...
,好吧,我想我们这里有3种选择:
A.多线程:
PHP本机不支持多线程。
但是有一个PHP扩展(实验性的)称为pthreads(https://github.com/krakjoe/pthreads),您可以执行此操作。
B.多进程:
这可以通过3种方式完成:
分叉
执行命令
管道
C.分布式并行处理:
怎么运行的:
Client
应用程序向引擎(MQ引擎)发送数据(又称JSON格式)(可以是JSON格式),或者“可以是本地或外部Web服务”
MQ Engine
将数据“大部分存储在内存中,还可以选择存储在数据库中”在队列内(您可以定义队列名称)
Client
App要求MQ引擎按顺序(FIFO或基于优先级)处理要处理的数据(消息),“您也可以从特定队列中请求数据”。
一些MQ引擎:
ZeroMQ(不错的选择,很难使用)
面向消息的IPC库,是Erlang中的Message Queue Server,将作业存储在内存中。它是一个充当并发框架的套接字库。集群产品和超级计算的速度比TCP快。
RabbitMQ(不错的选择,易于使用)
自托管企业消息队列,不是真正的工作队列-而是可以用作工作队列但需要其他语义的消息队列。
Beanstalkd(最佳选择,易于使用)
(Laravel内置支持,由Facebook构建,用于工作队列)-有一个“ Beanstalkd控制台”工具,非常好
齿轮工
(问题:用于分布式处理的集中经纪人系统)
Apache ActiveMQ
Java中最流行的开源消息代理,(问题:很多错误和问题)
亚马逊SQS
(Laravel内置支持,托管-因此不需要任何管理。实际上,工作队列不是必需的,因此需要额外的工作来处理语义,例如掩埋工作)
IronMQ
(Laravel内置支持,可编写于Go中,既有云版本也有内部版本可用)
雷迪斯
(Laravel内置支持,但速度不如其设计的那么快)
麻雀
(使用基于memcache的Ruby编写)
史达琳
(使用基于memcache的Ruby编写,内置于twitter)
红est
(只是另一个质量管理)
卡夫卡
(写在Scala的LinkedIn上)
EagleMQ
开源,高性能,轻量级的队列管理器(用C语言编写)
在这里可以找到更多的信息:http://queues.io
,如果您的应用程序要在Unix / Linux环境下运行,建议您使用fork选项。从根本上来说,这是孩子们玩的游戏。我已经将它用于Cron经理,并且如果不能进行分叉,则可以将其代码恢复为Windows友好的代码路径。
如您所述,多次运行整个脚本的选项确实增加了很多开销。如果您的脚本很小,则可能不是问题。但是您可能会习惯于按自己的方式在PHP中进行并行处理。下次当您有一项使用200mb数据的工作时,这很可能是个问题。因此,最好学习一种可以坚持的方式。
我也测试过Gearman,我非常喜欢。有一些事情需要考虑,但总体而言,它提供了一种很好的方式将作品分发到运行以不同语言编写的不同应用程序的不同服务器。除了进行设置外,实际上还可以从PHP或其他任何语言中使用它,这又是……孩子们玩耍。
对于您需要做的事情,这很可能是过大的。但是,在处理数据和作业时,它将为您带来新的可能性,因此,我建议您单凭这一事实尝试使用Gearman。
,我更喜欢exec()和gearman。
exec()很简单,没有连接,而且占用的内存更少。
Gearman应该需要套接字连接,而工作人员应该占用一些内存。
但是Gearman比exec()更灵活,更快。最重要的是它可以在其他服务器上部署工作程序。如果工作很耗时间和资源。
我在当前项目中使用Gearman。
,我使用PHP的pnctl-只要您知道自己所做的就很好。我了解您的情况,但我认为理解我们的代码并不困难,实现JOB队列或并行过程时,我们只需要比以往任何时候都更加自觉。
我认为,只要您对其进行完美编码,并确保流程顺畅无阻,则在实现时应牢记“并行过程”。
您可能会犯错误的地方:
循环-应该能够由GLOBAL变量处理。
处理某些交易集-只要您正确定义交易集,就应该能够完成它。
看一下这个例子-https://github.com/rakesh-sankar/Tools/blob/master/PHP/fork-parallel-process.php。
希望能帮助到你。
,“在PHP中轻松并行处理”中描述的方法非常可怕-原理还可以-但实现方式?正如您已经指出的,curl_multi_ fns提供了一种更好的方法来实现这种方法。
但是我认为这两种方式会增加很多开销
是的,您可能不需要客户端和服务器HTTP堆栈来完成任务-但是除非您为Google工作,否则开发时间比硬件成本要昂贵得多-并且有很多工具可以管理HTTP /分析性能-并且有一个定义的标准,涵盖了诸如状态通知和身份验证之类的内容。
解决方案的实现方式很大程度上取决于所需的事务完整性级别以及是否需要按顺序处理。
在您提到的方法中,我建议重点关注使用curl_multi_的HTTP请求方法。但是,如果您需要良好的事务控制/顺序传递,则一定要在消息源和处理代理之间运行一个代理守护程序(这里有一个编写良好的单线程服务器,适合用作代理的框架)。请注意,处理代理应一次处理一条消息。
如果您需要高度可伸缩的解决方案,请查看适当的消息队列系统,例如RabbitMQ。
高温超导
C。
,这是PHP中并行处理的一些选项的摘要。
安培
Checkout Amp-异步并发变得简单-这似乎是我见过的用于并行处理的最成熟的PHP库。
佩奇的工艺课
该类发布在PHP的exec()函数的注释中,并为派生新进程并对其进行跟踪提供了一个真正简单的起点。
例:
// You may use status(),start(),and stop(). notice that start() method gets called automatically one time.
$process = new Process(\'ls -al\');
// or if you got the pid,however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);
// Then you can start/stop/check status of the job.
$process.stop();
$process.start();
if ($process.status()) {
echo \"The process is currently running\";
} else {
echo \"The process is not running.\";
}
其他选项比较
还有一篇很棒的文章《 PHP中的异步处理或多任务处理》介绍了各种方法的优缺点:
pthreads扩展(另请参阅此SitePoint文章)
Amp \\ Thread库
hack \ async(需要运行Facebook的HHVM)
pcntl_fork
en
打开/卷曲/打开
门卫
然后,还有这个简单的教程,它被包装到一个名为Doorman的小库中。
希望这些链接为进一步的研究提供有用的起点。
,首先,此答案基于linux OS env。
另一个pecl扩展名是并行的,您可以通过发行pecl install parallel
进行安装,但它有一些先决条件:
安装ZTS(Zend线程安全)Build PHP 7.2+版本
如果按源构建此扩展,则应检查php.ini之类的配置文件,然后在其中添加extension=parallel.so
然后查看完整的示例要点:https://gist.github.com/krakjoe/0ee02b887288720d9b785c9f947f3a0a
或php官方网站网址:https://www.php.net/manual/zh/book.parallel.php