2020-07-05 16:36:28 +08:00
|
|
|
|
<?php
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | CatchAdmin [Just Like ~ ]
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Copyright (c) 2017~2020 http://catchadmin.com All rights reserved.
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Licensed ( https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt )
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Author: JaguarJack [ njphper@gmail.com ]
|
|
|
|
|
// +----------------------------------------------------------------------
|
2020-07-07 16:58:34 +08:00
|
|
|
|
namespace catcher\library\crontab;
|
|
|
|
|
|
|
|
|
|
use Swoole\Process;
|
|
|
|
|
use catcher\library\crontab\Process as MProcess;
|
2020-07-08 17:48:45 +08:00
|
|
|
|
use Swoole\Timer;
|
2020-07-07 16:58:34 +08:00
|
|
|
|
|
|
|
|
|
class ManageProcess
|
|
|
|
|
{
|
|
|
|
|
use RegisterSignal, MProcess, Store;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 动态扩展的最大 process 数量
|
|
|
|
|
*
|
|
|
|
|
* @var int
|
|
|
|
|
*/
|
|
|
|
|
protected $maxNum = 10;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 常驻 process
|
|
|
|
|
*
|
|
|
|
|
* @var int
|
|
|
|
|
*/
|
2020-07-08 17:48:45 +08:00
|
|
|
|
protected $staticNum = 1;
|
2020-07-07 16:58:34 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 存储 process 信息
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
2020-07-09 08:28:29 +08:00
|
|
|
|
protected $processes = [];
|
2020-07-07 16:58:34 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 主进程ID
|
|
|
|
|
*
|
|
|
|
|
* @var
|
|
|
|
|
*/
|
|
|
|
|
protected $master_pid;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* pid 文件名称
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
protected $mater = 'catch-master';
|
|
|
|
|
|
2020-07-09 15:41:53 +08:00
|
|
|
|
/**
|
|
|
|
|
* @var int
|
|
|
|
|
*/
|
|
|
|
|
protected $master_start_at;
|
|
|
|
|
|
2020-07-07 16:58:34 +08:00
|
|
|
|
/**
|
|
|
|
|
* process status 存储文件
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
protected $processStatus = 'process-status';
|
|
|
|
|
|
|
|
|
|
// 版本
|
|
|
|
|
const VERSION = '1.0.0';
|
|
|
|
|
|
|
|
|
|
// process 等待状态
|
|
|
|
|
const WAITING = 'waiting';
|
|
|
|
|
// process 繁忙状态
|
|
|
|
|
const BUSYING = 'busying';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 启动进程
|
|
|
|
|
*
|
|
|
|
|
* @time 2020年07月07日
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function start()
|
|
|
|
|
{
|
|
|
|
|
// 守护进程
|
2020-07-09 15:41:53 +08:00
|
|
|
|
// Process::daemon(true, false);
|
2020-07-07 16:58:34 +08:00
|
|
|
|
// alarm 信号
|
2020-07-08 17:48:45 +08:00
|
|
|
|
// Process::alarm(1000 * 1000);
|
2020-07-07 16:58:34 +08:00
|
|
|
|
// 1s 调度一次
|
2020-07-08 17:48:45 +08:00
|
|
|
|
$this->timeTick(1000, $this->schedule());
|
2020-07-07 16:58:34 +08:00
|
|
|
|
// 注册信号
|
|
|
|
|
$this->registerSignal();
|
|
|
|
|
// pid
|
|
|
|
|
$this->master_pid = getmypid();
|
2020-07-09 15:41:53 +08:00
|
|
|
|
$this->master_start_at = time();
|
2020-07-09 10:04:31 +08:00
|
|
|
|
// 存储 pid
|
|
|
|
|
$this->storeMasterPid($this->master_pid);
|
2020-07-09 15:41:53 +08:00
|
|
|
|
// 初始化文件
|
|
|
|
|
$this->initFiles();
|
2020-07-07 16:58:34 +08:00
|
|
|
|
// 初始化进程
|
|
|
|
|
$this->initProcesses();
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-08 17:48:45 +08:00
|
|
|
|
/**
|
|
|
|
|
* 自定义 tick 关闭协程
|
|
|
|
|
*
|
|
|
|
|
* @time 2020年07月08日
|
|
|
|
|
* @param int $time
|
|
|
|
|
* @param $callable
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
protected function timeTick(int $time, $callable)
|
|
|
|
|
{
|
|
|
|
|
// 关闭协程
|
|
|
|
|
Timer::set([
|
|
|
|
|
'enable_coroutine' => false,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
Timer::tick($time, $callable);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 16:58:34 +08:00
|
|
|
|
/**
|
|
|
|
|
* 调度
|
|
|
|
|
*
|
|
|
|
|
* @time 2020年07月07日
|
|
|
|
|
* @return \Closure
|
|
|
|
|
*/
|
|
|
|
|
protected function schedule()
|
|
|
|
|
{
|
|
|
|
|
return function () {
|
|
|
|
|
$schedule = new Schedule();
|
2020-07-09 15:41:53 +08:00
|
|
|
|
$schedule->command('catch:cache')->everyTenSeconds();
|
2020-07-07 16:58:34 +08:00
|
|
|
|
|
|
|
|
|
foreach ($schedule->getCronTask() as $cron) {
|
|
|
|
|
if ($cron->can()) {
|
|
|
|
|
list($waiting, $process) = $this->hasWaitingProcess();
|
|
|
|
|
if ($waiting) {
|
|
|
|
|
// 向 process 投递 cron
|
2020-07-09 15:41:53 +08:00
|
|
|
|
var_dump(serialize($cron));
|
|
|
|
|
$process->push(serialize($cron));
|
2020-07-07 16:58:34 +08:00
|
|
|
|
} else {
|
|
|
|
|
// 创建临时 process 处理,处理完自动销毁
|
|
|
|
|
$this->createProcess($cron);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create Task
|
|
|
|
|
*
|
|
|
|
|
* @time 2019年08月06日
|
|
|
|
|
* @param Cron $cron
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
protected function createProcess(Cron $cron)
|
|
|
|
|
{
|
|
|
|
|
$process = new Process(function (Process $process) use($cron) {
|
2020-07-09 10:04:31 +08:00
|
|
|
|
$cron->run();
|
2020-07-07 16:58:34 +08:00
|
|
|
|
$process->exit();
|
|
|
|
|
});
|
|
|
|
|
|
2020-07-08 17:48:45 +08:00
|
|
|
|
// $process->name(sprintf('worker: '));
|
2020-07-07 16:58:34 +08:00
|
|
|
|
|
|
|
|
|
$process->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建静态 worker 进程
|
|
|
|
|
*
|
|
|
|
|
* @time 2020年07月05日
|
|
|
|
|
* @return Process
|
|
|
|
|
*/
|
|
|
|
|
protected function createStaticProcess()
|
|
|
|
|
{
|
2020-07-08 17:48:45 +08:00
|
|
|
|
$process = new Process($this->createProcessCallback());
|
|
|
|
|
|
|
|
|
|
// 使用非阻塞队列
|
|
|
|
|
$process->useQueue(1, 2|Process::IPC_NOWAIT);
|
|
|
|
|
|
|
|
|
|
return $process;
|
2020-07-07 16:58:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化 workers
|
|
|
|
|
*
|
|
|
|
|
* @time 2020年07月03日
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
protected function initProcesses()
|
|
|
|
|
{
|
2020-07-09 15:41:53 +08:00
|
|
|
|
|
2020-07-09 08:37:03 +08:00
|
|
|
|
|
2020-07-07 16:58:34 +08:00
|
|
|
|
for ($i = 0; $i < $this->staticNum; $i++) {
|
|
|
|
|
|
|
|
|
|
$process = $this->createStaticProcess();
|
|
|
|
|
// $worker->name("[$i+1]catch-worker");
|
2020-07-09 08:28:29 +08:00
|
|
|
|
|
2020-07-07 16:58:34 +08:00
|
|
|
|
$process->start();
|
|
|
|
|
|
2020-07-09 08:28:29 +08:00
|
|
|
|
$this->processes[$process->pid] = $process;
|
|
|
|
|
|
|
|
|
|
$this->storeStatus($this->processInfo($process));
|
2020-07-07 16:58:34 +08:00
|
|
|
|
}
|
2020-07-09 10:04:31 +08:00
|
|
|
|
|
|
|
|
|
$this->saveProcessStatus();
|
2020-07-07 16:58:34 +08:00
|
|
|
|
}
|
2020-07-08 17:48:45 +08:00
|
|
|
|
|
|
|
|
|
/**
|
2020-07-09 15:41:53 +08:00
|
|
|
|
* 初始化文件
|
2020-07-08 17:48:45 +08:00
|
|
|
|
*
|
2020-07-09 15:41:53 +08:00
|
|
|
|
* @time 2020年07月09日
|
2020-07-08 17:48:45 +08:00
|
|
|
|
* @return void
|
|
|
|
|
*/
|
2020-07-09 15:41:53 +08:00
|
|
|
|
protected function initFiles()
|
2020-07-08 17:48:45 +08:00
|
|
|
|
{
|
2020-07-09 15:41:53 +08:00
|
|
|
|
file_put_contents($this->getProcessStatusPath(), '');
|
|
|
|
|
file_put_contents($this->schedulePath() . 'error.log', '');
|
2020-07-08 17:48:45 +08:00
|
|
|
|
}
|
2020-07-07 16:58:34 +08:00
|
|
|
|
}
|