PHP|PHP 多进程任务 spatie/async 扩展使用说明
【PHP|PHP 多进程任务 spatie/async 扩展使用说明】spatie/async
是为 PHP 基于 PCNTL
扩展开发的,能够使用多进程处理任务。
项目地址
spatie/async
常规使用示例
对象形式
use Spatie\Async\Pool;
$pool = Pool::create()
// 选择执行 PHP
->withBinary('/path/to/php')
// 可同时运行的最大进程数
->concurrency(20)
// 进程完成所需的最长时间(以秒为单位),支持小数点位置以实现更细粒度的超时
->timeout(15)
// 配置应该使用哪个自动加载器子流程
->autoload(__DIR__ . '/../../vendor/autoload.php')
// 配置循环应该休眠多长时间,然后重新检查进程状态(以微秒为单位)。
->sleepTime(50000);
foreach ($things as $thing) {
$pool->add(function () use ($thing) {
// 添加任务
})->then(function ($output) {
// 任务执行完毕回调函数,返回结果会以变量 $output 注入回调函数// $pool->stop();
提前终止 pool 任务池执行,终止后想要继续使用则需要重新创建任务池
})->catch(function (MyException $e) {
// 捕捉异常
})
->catch(function (Exception $e) {
// / 捕捉异常,支持不做多个
})->timeout(function () {
// 超时处理
});
}
$pool->wait();
函数使用方式
use Spatie\Async\Pool;
$pool = Pool::create();
foreach (range(1, 5) as $i) {
$pool[] = async(function () {
usleep(random_int(10, 1000));
return 2;
})->then(function (int $output) {
echo $output.PHP_EOL;
});
}await($pool);
任务类使用方式 需要创建任务类,并继承类
Spatie\Async\Task
,任务执行会调用 task 任务类的 run()
方法use Spatie\Async\Task;
class MyTask extends Task
{
public function configure()
{
// 加载配置,如:依赖容器、核心类加载
}public function run()
{
// 任务工作程序
}
}// Add the task to the pool
$pool = Pool::create();
$pool->add(new MyTask());
$pool->wait();
补充:在 Laravel 中使用注意 如果没有加载
bootstrap/app.php
配置,则无法使用 Laravel 提供的类方法。比如:使用 Illuminate\Support\Facades\Log
时会报异常 Exception: A facade root has not been set
未加载
bootstrap/app.php
示例 'use Log','msg' => '未加载 bootstrap/app.php', 'datetime' => $datetime]);
}
}
报错信息如下
[2022-03-28 17:26:17] local.ERROR: EmployTask {"msg":"A facade root has not been set.#0 /www/wwwroot/laravel/app/Task/EmployTask.php(23): Illuminate\\Support\\Facades\\Facade::__callStatic()
#1 /www/wwwroot/laravel/app/Task/EmployTask.php(17): App\\Task\\EmployTask->test()
#2 /www/wwwroot/laravel/vendor/spatie/async/src/Task.php(15): App\\Task\\EmployTask->run()
#3 /www/wwwroot/laravel/vendor/spatie/async/src/Runtime/ChildRuntime.php(26): Spatie\\Async\\Task->__invoke()
#4 {main}"}
加载
bootstrap/app.php
示例make(\Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
}public function run()
{
$datetime = date('Y-m-d H:i:s');
Log::error('EmployTask',['type' => 'use Log','msg' => '加载 bootstrap/app.php', 'datetime' => $datetime]);
}
}// 也可以这样使用$pool[] = async(function () use ($result, $syncemployRepository) {
$app = require __DIR__.'/../../../../bootstrap/app.php';
$kernel = $app->make(\Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
// 任务代码
})->then(function ($output) use($pool) {
$pool->stop();
})->catch(function (Exception $e) {
Log::error('createauth_sync', ['msg' => $e->getMessage()]);
});
记录日志如下
[2022-03-28 17:28:26] local.ERROR: EmployTask {"type":"use Log","msg":"加载 bootstrap/app.php","datetime":"2022-03-28 17:28:26"}
原因说明
作者在文档中有说明
Besides using closures, you can also work with a Task. A Task is useful in situations where you need more setup work in the child process. Because a child process is always bootstrapped from nothing, chances are you'll want to initialise eg. the dependency container before executing the task. The Task class makes this easier to do.(除了可以使用闭包,还可以使用 Task 任务。使用者有可能需要在子进程中加载更多设置。子进程总是从零开始启动的,所以就需要进行初始化。比如:加载依赖容器、核心类)
推荐阅读
- ARM-高效C编程|第四篇 ARM C 高效编程 - 多条件判断
- B树、B+树速记
- 对象、数组、函数等多种数据类型的深浅克隆(拷贝)
- c++堆排序和堆
- 目标检测|基于ZYNQ的帧差法多运动目标检测(开源)
- C++的多态与虚函数你了解吗
- Java多线程学习笔记(六) 长乐未央篇
- 渗透小圈|信息收集那些事
- 源码阅读分析-PHP-laravel
- 浅谈systemd原理和应用