# 案例:实现一个Master、Worker的进程 背景:在编写服务端程序的时候单进程的消费速度跟不上,这时候可以选择多进程来操作,选择多进程为了防止进程死掉导致任务无法执行,所以采用Master、Worker进程模型实现一个进程管理。 ```php <?php class SunnyProcess{ // Master进程id protected static $masterPid; // Worker进程id集合 protected static $workerPid = []; /** * 设置进程名称 * @String $name 进程名称 */ public static function setProcessTitle($name){ if (extension_loaded('proctitle') && function_exists('setproctitle')) { @setproctitle($name); } elseif (version_compare(phpversion(), "5.5", "ge") && function_exists('cli_set_process_title')) { @cli_set_process_title($name); } } /** * 创建Worker进程 * @Int $num Worker进程数量 */ public static function forkWorker($num = 2){ for($i=0;$i<$num;$i++){ $pid = pcntl_fork(); if($pid>0){ // 父进程,把子进程id存到进程集合 static::$workerPid[$pid] = $pid; }elseif($pid===0){ // 子进程 static::setProcessTitle("php:worker"); while(1){ // 获取当前进程id $pids = posix_getpid(); $time = microtime(true); $masterpid = static::$masterPid; echo "主进程:{$masterpid},当前进程:{$pids},当前时间:{$time}\n"; sleep(1); } }else{ exit('进程启动失败\n'); } } } /** * Master进程监控Worker进程 */ public static function monitor(){ while(true){ // 挂起当前进程的执行直到一个子进程退出或接收到一个信号 $status = 0; // 使用pcntl_wait挂起当前进程,挂起之后会阻塞不执行pcntl_wait之后的代码 // 直到pcntl_wait返回pid $pid = pcntl_wait($status, WUNTRACED); var_dump($pid);//这段代码往后的代码只有在pcntl_wait有触发的时候才会调用 pcntl_signal_dispatch(); if ($pid >= 0) { // worker健康检查 unset(static::$workerPid[$pid]); echo "worker检查:{$pid}\n"; static::forkWorker(1); print_r(static::$workerPid);echo "\n"; } } } public static function runAll(){ static::setProcessTitle("php:master"); static::$masterPid = posix_getpid(); static::forkWorker(3); static::monitor(); } } SunnyProcess::runAll(); ```