# 案例:实现一个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();
```
- 第一章:基础知识
- 课程简介
- PHP-FPM过渡常驻内存
- 进程
- 实战:实现Master-Worker
- 线程
- 实战:CC攻击器
- 协程
- 实战:实现waitGroup功能
- 进程、线程、协程的区别
- 第二章:初识Swoft2.0
- Swoft介绍
- Swoft环境安装
- gcc升级
- 安装Swoft框架
- 目录结构介绍
- SwoftCli工具
- Swoft配置
- 第三章:Swoft2.0核心
- 上下文
- 常驻内存没有上下文隔离
- 实战:手写swoole框架上下文管理
- Bean容器
- 实战:根据容器原理实现容器
- 实战:通过容器实现依赖注入
- Bean容器定义与使用
- 配置文件定义Bean
- 容器类型
- 面向接口的容器
- 注解
- 实战:实现注解
- 自定义Swoft注解类
- 事件
- 连接池
- 实战:Swoole实现连接池
- 第四章:Http服务器
- Http Server生命周期
- Http Server配置
- 控制器
- 路由
- 请求对象Request
- 响应对象Response
- Http异常处理
- 中间件
- 实战:中间件实现JWT登陆授权
- 第五章:验证器
- 内置验证类型
- 验证器的使用
- 自定义验证器
- 第六章:数据库操作
- 连接数据库
- 实体模型
- 模型事件
- 查询器
- 事务处理
- 连接池配置
- 读写分离
- 多数据库切换
- Models分层结构
- 实战:实现用户CURD API
- 第七章:Redis
- 连接redis和使用
- Redis连接池
- Redis集群配置(单机版)
- Redis集群配置(多服务器)
- Redis连接集群
- Redis实战:实现延时任务
- 第八章:AOP编程
- AOP概念
- AOP实现原理
- 实战实现AOP:静态代理
- 实战实现AOP:动态代理
- 切面注解介绍
- PointExecution切面
- PointBean切面
- PointAnnotation切面
- 实战:使用AOP实现日志记录
- 第九章:任务处理
- 进程使用
- 进程池使用
- 实战:进程消费队列
- 实战:进程实现RabbitMQ延时队列
- 异步任务
- 协程任务
- 定时任务