自定义进程

PHP自带的pcntl存在许多不足,不支持重定向标准输入和输出及进程间通信的功能,且容易使用错误。
EasySwoole基于SwooleProcess模块进行了封装,来创建工作进程,用于处理耗时任务,消息队列,等其它的特殊任务。
EasySwoole启动时,会自动创建注册的进程,并执行进程指定的逻辑代码,进程意外退出时,会被重新拉起。

创建一个自定义进程

需要定义一个进程类继承EasySwoole\Component\Process\AbstractProcess

定义进程内执行逻辑回调

  1. protected function run($arg)
  2. {
  3. // TODO: Implement run() method.
  4. $this->getProcessName(); // 获取注册进程名称
  5. $this->getProcess(); // 获取进程实例 \Swoole\Process
  6. $this->getPid(); // 获取当前进程Pid
  7. $this->getArg(); // 获取注册时传递的参数
  8. }

进程间通信Pipe回调

  1. protected function onPipeReadable(Process $process)
  2. {
  3. // 该回调可选
  4. // 当主进程对子进程发送消息的时候 会触发
  5. $process->read(); // 读取消息
  6. }

进程间异常回调

  1. protected function onException(\Throwable $throwable, ...$args)
  2. {
  3. // 该回调可选
  4. // 捕获run方法内抛出的异常
  5. // 这里可以通过记录异常信息来帮助更加方便的知道出现问题的代码
  6. }

进程信号回调

  1. protected function onSigTerm()
  2. {
  3. // 当进程接收到 SIGTERM 信号触发该回调
  4. }

进程意外退出回调

  1. protected function onShutDown()
  2. {
  3. // 该回调可选
  4. // 进程意外退出 触发此回调
  5. // 大部分用于清理工作
  6. }

注册进程

EasySwoole 全局的 mainServerCreate 事件中进行进程注册

  1. $processConfig = new \EasySwoole\Component\Process\Config([
  2. 'processName' => 'CustomProcess', // 设置 自定义进程名称
  3. 'processGroup' => 'Custom', // 设置 自定义进程组名称
  4. 'arg' => [
  5. 'arg1' => 'this is arg1!'
  6. ], // 【可选参数】设置 注册进程时要传递给自定义进程的参数,可在自定义进程中通过 $this->getArg() 进行获取
  7. 'enableCoroutine' => true, // 设置 自定义进程自动开启协程
  8. ]);
  9. \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new CustomProcess($processConfig));

推荐使用 \EasySwoole\Component\Process\Manager 类进行注册自定义进程,注册方式示例代码如上所示。如果您的框架版本过低,不支持 \EasySwoole\Component\Process\Manager 类,可使用如下方式进行注册自定义进程: \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer()->addProcess((new TickProcessnew CustomProcess($processConfig));

完整示例代码

1. 定义自定义进程类示例

首先,我们定义一个自定义进程类继承 \EasySwoole\Component\Process\AbstractProcess 类,示例代码如下:

  1. <?php
  2. namespace App\Process;
  3. use EasySwoole\Component\Process\AbstractProcess;
  4. use Swoole\Process;
  5. class CustomProcess extends AbstractProcess
  6. {
  7. protected function run($arg)
  8. {
  9. // TODO: Implement run() method.
  10. $processName = $this->getProcessName(); // 获取 注册进程名称
  11. $swooleProcess = $this->getProcess(); // 获取 注册进程的实例 \Swoole\Process
  12. $processPid = $this->getPid(); // 获取 当前进程 Pid
  13. $args = $this->getArg(); // 获取 注册进程时传递的参数
  14. var_dump('### 开始运行自定义进程 start ###');
  15. var_dump($processName, $swooleProcess, $processPid, $args);
  16. var_dump('### 运行自定义进程结束 end ###');
  17. }
  18. protected function onPipeReadable(Process $process)
  19. {
  20. // 该回调可选
  21. // 当主进程对子进程发送消息的时候 会触发
  22. $recvMsgFromMain = $process->read(); // 用于获取主进程给当前进程发送的消息
  23. var_dump('收到主进程发送的消息: ');
  24. var_dump($recvMsgFromMain);
  25. }
  26. protected function onException(\Throwable $throwable, ...$args)
  27. {
  28. // 该回调可选
  29. // 捕获 run 方法内抛出的异常
  30. // 这里可以通过记录异常信息来帮助更加方便地知道出现问题的代码
  31. }
  32. protected function onShutDown()
  33. {
  34. // 该回调可选
  35. // 进程意外退出 触发此回调
  36. // 大部分用于清理工作
  37. }
  38. protected function onSigTerm()
  39. {
  40. // 当进程接收到 SIGTERM 信号触发该回调
  41. }
  42. }

2. 注册进程示例

然后在 mainServerCreate 事件中进行注册进程,示例代码如下:

  1. <?php
  2. namespace EasySwoole\EasySwoole;
  3. use EasySwoole\EasySwoole\AbstractInterface\Event;
  4. use EasySwoole\EasySwoole\Swoole\EventRegister;
  5. class EasySwooleEvent implements Event
  6. {
  7. public static function initialize()
  8. {
  9. date_default_timezone_set('Asia/Shanghai');
  10. }
  11. public static function mainServerCreate(EventRegister $register)
  12. {
  13. $processConfig = new \EasySwoole\Component\Process\Config([
  14. 'processName' => 'CustomProcess', // 设置 进程名称为 TickProcess
  15. 'processGroup' => 'Custom', // 设置 进程组名称为 Tick
  16. 'arg' => [
  17. 'arg1' => 'this is arg1!',
  18. ], // 传递参数到自定义进程中
  19. 'enableCoroutine' => true, // 设置 自定义进程自动开启协程环境
  20. ]);
  21. // 【推荐】使用 \EasySwoole\Component\Process\Manager 类注册自定义进程
  22. $customProcess = (new \App\Process\CustomProcess($processConfig));
  23. // 【可选操作】把 tickProcess 的 Swoole\Process 注入到 Di 中,方便在后续控制器等业务中给自定义进程传输信息(即实现主进程与自定义进程间通信)
  24. \EasySwoole\Component\Di::getInstance()->set('customSwooleProcess', $customProcess->getProcess());
  25. // 注册进程
  26. \EasySwoole\Component\Process\Manager::getInstance()->addProcess($customProcess);
  27. /*
  28. #【针对于低版本不支持 \EasySwoole\Component\Process\Manager 类】可使用 \EasySwoole\EasySwoole\ServerManager 类注册自定义进程
  29. $customProcess = (new \App\Process\CustomProcess($processConfig))->getProcess();
  30. // 【可选操作】把 tickProcess 的 Swoole\Process 注入到 Di 中,方便在后续控制器等业务中给自定义进程传输信息(即实现主进程与自定义进程间通信)
  31. \EasySwoole\Component\Di::getInstance()->set('customSwooleProcess', $customProcess);
  32. // 注册进程
  33. \EasySwoole\EasySwoole\ServerManager::getInstance()->getSwooleServer()->addProcess($customProcess);
  34. */
  35. }
  36. }

3. 向自定义进程中传递消息

  1. <?php
  2. namespace App\HttpController;
  3. use EasySwoole\Component\Di;
  4. use EasySwoole\Http\AbstractInterface\Controller;
  5. class Index extends Controller
  6. {
  7. public function index()
  8. {
  9. // 获取 Di 中注入的 自定义进程
  10. $customProcess = Di::getInstance()->get('customSwooleProcess');
  11. // 向自定义进程中传输信息,会触发自定义进程的 onPipeReadable 回调
  12. $customProcess->write('this is test!');
  13. }
  14. }

进程管理命令说明

EasySwoole 内置了对于 Process 的命令行操作,方便开发者非常友好地去管理 Process

可执行 php easyswoole process -h 来查看具体操作。

显示所有进程

php easyswoole process show

如果想要以 MB 形式显示:

php easyswoole process show -d

杀死指定进程(PID)

php easyswoole process kill —pid=PID

杀死指定进程组(GROUP)

php easyswoole process kill —group=GROUP_NAME

杀死所有进程

php easyswoole process killAll

强制杀死进程

需要带上 -f 参数,例如:

php easyswoole process kill —pid=PID -f