fastbill/parallel-process-dispatcher

该包的最新版本(1.2.1)没有可用的许可证信息。

用于在后台和/或在并行中运行作业的微型PHP库

1.2.1 2017-12-05 19:26 UTC

This package is auto-updated.

Last update: 2024-09-29 05:02:00 UTC


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中注册运行的工作进程,让工作进程互知。