mojiehai / process_manage
进程管理
Requires
- php: >=7.0
- ext-json: *
- ext-mbstring: *
- ext-pcntl: *
- ext-posix: *
This package is auto-updated.
Last update: 2024-09-09 18:18:36 UTC
README
php多进程管理器
业务场景
在实际业务场景中,我们可能需要定时执行或者近乎实时到业务逻辑,简单的可以使用unix自带的crontab实现。但是对于一些实时性要求比较高的业务就不适用了,所以我们就需要一个常驻内存的任务管理工具,为了保证实时性,一方面我们让它一直执行任务(适当的睡眠,保证cpu不被100%占用),另一方面我们实现多进程保证并发的执行任务。
简述
基于php-cli模式实现master(父进程)-worker(子进程)的多进程管理器。
- 创建:一个master fork出多个worker
- 运行:
- master通过信号(signal)控制多个worker的生命周期(master会阻塞的等待信号或者子进程退出)
- worker会在生命周期中执行预定的任务
依赖
- php: >=7.0
- ext-pcntl: *
- ext-posix: *
- ext-json: *
- ext-mbstring: *
安装
linux:
composer require mojiehai/process_manage
windows:
composer require mojiehai/process_manage --ignore-platform-reqs(windows下仅安装,不支持使用)
使用
- 启动
$config = [ // 进程基础配置 'titlePrefix' => 'process_m', // 进程前缀 'baseTitle' => 'test', // 进程基础名称 // master 进程配置 'checkWorkerInterval' => 0, // n秒检测一次进程(<=0则为不检测) 'maxWorkerNum' => 1, //1个进程 // worker 进程配置 'executeTimes' => 1, // 任务的最大执行次数(0为没有最大执行次数,一直执行) 'executeUSleep' => 10000000, // 每次执行任务睡眠时间(微秒) 1s = 1 000 000 us (1s) 'limitSeconds' => 10800, // 工作进程最大执行时长(秒)(跑3个小时重启) ]; try { // 创建进程管理器 (new Manage($config)) ->setWorkInit( // 工作内容初始化 function (Process $process) { // init \ProcessManage\Log\ProcessLog::Record('info', $process, 'work init ... '); } ) ->setWork( // 执行的工作内容 function(Worker $process) { // work \ProcessManage\Log\ProcessLog::Record('info', $process, 'work run ... '); }) ->start(); } catch (ProcessException $e) { echo $e->getExceptionAsString(); }
- 停止
$config = [ // 进程基础配置 'baseTitle' => 'test', // 进程基础名称 ]; try { // 创建进程管理器 (new Manage($config))->stop(); } catch (ProcessException $e) { echo $e->getExceptionAsString(); }
- 平滑重启
$config = [ // 进程基础配置 'titlePrefix' => 'process_m', // 进程前缀 'baseTitle' => 'test', // 进程基础名称 // master 进程配置 'checkWorkerInterval' => 0, // n秒检测一次进程(<=0则为不检测) 'maxWorkerNum' => 1, //1个进程 // worker 进程配置 'executeTimes' => 1, // 任务的最大执行次数(0为没有最大执行次数,一直执行) 'executeUSleep' => 10000000, // 每次执行任务睡眠时间(微秒) 1s = 1 000 000 us (1s) 'limitSeconds' => 10800, // 工作进程最大执行时长(秒)(跑3个小时重启) ]; try { // 创建进程管理器 (new Manage($config)) ->setWorkInit( // 工作内容初始化 function (Process $process) { // init \ProcessManage\Log\ProcessLog::Record('info', $process, 'work init ... '); } ) ->setWork( // 执行的工作内容 function(Worker $process) { // work \ProcessManage\Log\ProcessLog::Record('info', $process, 'work run ... '); }) ->setBackground()->restart(); } catch (ProcessException $e) { echo $e->getExceptionAsString(); }
- 查看信息
$config = [ // 进程基础配置 'baseTitle' => 'test', // 进程基础名称 ]; try { // 创建进程管理器 (new Manage($config))->showStatus(); } catch (ProcessException $e) { echo $e->getExceptionAsString(); }
注意:baseTitle(进程基础名称)为进程的标识,start/stop/restart/status指定的名称必须相同。
说明
- 参数说明
-
固定配置(通过Config类的子类加载,作用域为全局,可在业务入口文件中指定)。例如
ProcessConfig::LoadConfig(["TitlePrefix" => "test"])-
进程配置,通过
ProcessConfig::LoadConfig($configArray)加载,配置项如下: -
日志配置,通过
LogConfig::LoadConfig($configArray)加载,配置项如下
-
-
非固定配置(通过manage构造函数加载进去,作用域为本次manage管理的进程)
-
- 方法说明
-
Manage类(单任务多进程管理器)
-
ManageMultiple类(多任务多进程管理器)
-
Process类
-
Worker类(继承Process类)
-
Master类(继承Process类)
-
- 示例或说明
- 1.0
(new Manage($config))->setWorkInit( // 工作内容初始化 function (Worker $process) { // init $link = mysqli_connect(...); ... $redis = new Redis(...); ... return ['mysql' => $link, 'redis' => $redis]; } )
- 1.1
(new Manage($config))->setWork( // 执行的工作内容 function(Worker $process, $result = []) { // work $mysqlLink = $result['mysql']; $redisLink = $result['redis']; }) )
- 1.2
字段说明:(Master表示主进程,Worker表示工作进程)[root@localhost command]# php cmd.php status Master type pid title memory(m) start run(s) count Master 29570 process_m:Master:test 0.661(693296b) 2018-12-23 17:29:01 6 2 Worker type pid title memory(m) start run(s) work Worker 29571 process_m:Worker:test 0.661(692760b) 2018-12-23 17:29:01 6 1 Worker 29572 process_m:Worker:test 0.661(693608b) 2018-12-23 17:29:01 6 1type:进程类型说明(Master/Worker)pid:进程pidtitle:进程名称memory:内存消耗,单位:M,括号中的为字节数start:进程开始时间run:运行时长,单位:秒count:(Master进程独有属性)当前子进程个数work:(Worker进程独有属性)当前进程执行任务回调的次数
- 1.0
命令管理
提供了一套命令管理的方案,通过实现部分接口即可接入
- 简述
该方案为自定义命令,但是有部分预定义命令。- 预定义命令:所有命令均有的基本行为,权重最高。预定义命令列表如下:
--help: 查看命令列表
- 自定义命令:分为两个部分,一部分为行为参数(必填参数),一部分为附加参数(选填参数)。(需要定义模板)
一条命令由一个明确的行为参数确定行为动作,若干个附加参数附带其他信息配置等。
例如:start -d行为参数为start,表示启动,附加参数d,表示后台运行
- 预定义命令:所有命令均有的基本行为,权重最高。预定义命令列表如下:
- 命令模板
- 格式
<>包裹着为必填参数(行为参数),参数可选值用 | 分隔[]包裹着为选填参数(附加参数),参数可选值用 | 分隔- 附加参数前缀必须带上
-
- 注意事项:
- 行为参数只能有一个,且只能在最前面一项
- 附加参数可以有多个,在行为参数后面
- 输入命令时,每个附加参数可以连上
=号传递想输入的参数
- 例如:
<start|stop|restart> -[d] -[a|s]
- 格式
- 构建命令
-
创建行为动作类继承
ProcessManage\Command\Action类,并实现下列方法:(一个行为动作一个类)- handler()
执行该命令的动作 - getCommandStr()
返回命令字符串 - getCommandDescription()
返回命令描述
- handler()
-
创建附加参数类继承
ProcessManage\Command\Options类,并实现下列方法:(一个附加参数一个类)- getCommandStr()
返回命令字符串 - getCommandDescription()
返回命令描述 - impactAction(Action $action)
影响action的行为方式,建议在这个方法中使用$action->setParam('key', 'value');给action设置参数,然后在action类的handler方法中通过$this->getParam($key)获取参数,进行操作。例如:/** * 影响action的行为 * @param Action $action * @return mixed */ public function impactAction(Action $action) { // $this->param 存储了用户输入的这个附加参数所带的值 $action->setParam('runInBackground', true); }
- getCommandStr()
-
创建模板类继承
ProcessManage\Command\Template类,并实现下列内容:(一个命令一个模板)- $mapping
命令映射关系(把action、options映射到具体的类),例如:/** * 命令映射的类 * @var array */ public $mapping = [ 'action' => [ 'start' => '\ProcessManage\Command\Action\Start', 'stop' => '\ProcessManage\Command\Action\Stop', 'restart' => '\ProcessManage\Command\Action\ReStart', ], 'options' => [ 'd' => '\ProcessManage\Command\Options\D', ], ];
- getTemplateStr()
定义模板格式,例如:/** * 获取模板内容 * @return string */ public function getTemplateStr() { return '<start|stop|restart> -[d]'; }
- $mapping
-
- 使用
use ProcessManage\Command\Command; use ProcessManage\Command\Template\ManageProcessTemplate; $command = new Command(new ManageProcessTemplate()); $command->run();
- 运行
[root@localhost command]# php cmd.php --help Usage: <start|stop|restart|status> -[d] action: start start process stop stop process restart restart process status process status options: -d background running process other: --help to display the list of available commands, please use the list command.