fastbill / parallel-process-dispatcher
该包的最新版本(1.2.1)没有可用的许可证信息。
用于在后台和/或在并行中运行作业的微型PHP库
1.2.1
2017-12-05 19:26 UTC
Requires
- php: >=5.4,<8.0-DEV
Requires (Dev)
README
此微库有两个类。一个将(Linux命令行)进程封装成对象,并允许异步运行而不出现死锁。另一个是多进程调度器,它接受任意数量的上述进程并同时运行它们(最多同时运行的进程数)。
使用示例
- 调度长时间运行的cron作业,例如,主要等待web服务响应(可以运行比最大CPU更多的进程)
- 运行监听队列的后台工作进程(最大应该是CPU的数量)
- 同时在一个Web应用程序中运行命令行任务,例如PDF生成、图像处理等。
安装
将以下内容添加到您的composer.json
{ "require": { "fastbill/parallel-process-dispatcher": "*" } }
或者在项目的根目录下运行以下命令
$ composer require "fastbill/parallel-process-dispatcher"
使用方法
类
进程
$process = new Process('pngcrush --brute background.png'); $process->start(); // optional: do something else in your application while (! $process->isFinished() ) { usleep(1000); //wait 1ms until next poll } echo $process->getOutput();
调度器
$process1 = new Process('pngcrush --brute background.png'); $process2 = new Process('pngcrush --brute welcome.png'); $process3 = new Process('pngcrush --brute logo.png'); $dispatcher = new Dispatcher(2); // will make sure only two of those will actually run at the same time $dispatcher->addProcess($process1); $dispatcher->addProcess($process2); $dispatcher->addProcess($process3); $dispatcher->dispatch(); // this will run until all processes are finished. $processes = $dispatcher->getFinishedProcesses(); foreach ($processes as $process) { echo $process->getOutput(), "\n\n"; }
高级
使用进程和调度器启动多个进程并在以后收集结果
$dispatcher = new Dispatcher(2); $process1 = new Process('pngcrush --brute background.png'); $dispatcher->addProcess($process1, true); // true starts the process if there are still free slots // [... more code ...] $process2 = new Process('pngcrush --brute welcome.png'); $dispatcher->addProcess($process2, true); // [... more code ...] // during code execution, the dispatcher cannot remove finished processes from the stack, so you have to call the tick()-function // if you want the queue to advance - but it's optional since at latest the __destruct() function will call dispatch(); $dispatcher->tick(); // [... more code ...] $dispatcher->dispatch(); // this will make the dispatcher wait until all the processes are finished, if they are still running $processes = $dispatcher->getFinishedProcesses(); // loop over results
已知问题
进程
- PHP内部:请注意,如果子进程产生输出,它将写入缓冲区,直到缓冲区满。如果缓冲区已满,子进程将暂停,直到父进程从缓冲区读取并腾出更多空间。这是在isFinished()方法中完成的。调度器定期调用此方法以防止死锁。如果您单独使用进程类,您有两种方法可以防止这种情况:
- 在自己的循环、使用tick函数或其他方式在脚本执行期间自行调用isFinished()
- 而不是写入stdOut,将输出重定向到临时文件,并使用其名称作为输出。
调度器
- 多个调度器(在不同进程)之间互不感知。因此,如果您的脚本使用调度器调用另一个脚本,而该脚本本身又使用调度器来创建多个进程,您将最终拥有超过最大值的子进程,因此请相应地选择最大值或使用队列(例如Redis)并通过例如在redis-stack中注册运行的工作进程,让工作进程互知。