php,pcntl_fork,多进程处理数据,这里需要注意的是,如果是处理数据库数据,并发量会将数据库的资源占满,要注意数据资源的分配
<?php
namespace App\Console\Commands\WorkCustomer;
use TaskDetail;
class TaskMore extends Command
{
/**
* 每个进程处理的条数
*/
public $maxDataCount;
/**
* 最大的子进程数量
*/
public $maxChildPro = 50;
/**
* 当前的子进程数量
*/
public $curChildPro = 0;
//当子进程退出时,会触发该函数,当前子进程数-1
public function sig_handler($sig)
{
global $curChildPro;
switch ($sig) {
case SIGCHLD:
echo 'SIGCHLD', PHP_EOL;
$curChildPro--;
break;
}
}
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'task_more';
/**
* 说明
* The console command description.
*
* @var string
*/
protected $description = '任务-多进程';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
try {
$allTaskDetailCount = TaskDetail::query()->where([
'task_id' => $taskId
])->count(); // 当前任务,详情数量
$this->maxDataCount = (int)ceil($allTaskDetailCount / $this->maxChildPro); // 总条数÷最大子进程,获取到每个进城最大处理的条数
if ($this->maxDataCount == 0) {
throw new \Exception('未找到数据');
}
while ($this->curChildPro < $this->maxChildPro) {
$this->curChildPro++;
$pid = pcntl_fork();
if ($pid == -1) {
throw new \Exception('fork子进程失败!');
} else {
if ($pid) {
// 阻塞父进程,直到子进程结束,不适合需要长时间运行的脚本.可使用pcntl_wait($status, WNOHANG)实现非阻塞式
pcntl_wait($status, WNOHANG);
} else {
// 这里开始处理逻辑
$s = rand(2, 6);
sleep($s);
exit;
}
}
}
}
} catch (\Exception $e) {
Log::info('task_more:error' . $e->getMessage());
}
}
}