# 案例:實現一個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延時隊列
- 異步任務
- 協程任務
- 定時任務