php内核 单进程协程与多进程模型内核差异
--- 下面给你3份代码1. 多进程模型pcntl_fork2. 单进程协程模型Swoole 协程3. 推荐的最佳实践多进程 每进程协程Swoole 多 worker coroutine server --- 先说最短结论大白话 - 多进程像开4家店每家店独立接单。稳不互相污染但成本高。 - 单进程协程像1家店里有个超级调度员同一批人来回切任务。省资源高并发强但代码必须“非阻塞、协程安全”。 - 最佳实践多店 每店高效调度也就是“多进程 协程”。 --- 代码1多进程模型纯 PHPpcntl ▎ 文件multi_process_demo.php?php declare(strict_types1);/** * 多进程演示 * - 主进程 fork 出 N 个子进程 * - 每个子进程独立处理任务 * - 用sleep模拟阻塞 IO */if(!function_exists(pcntl_fork)){fwrite(STDERR,pcntl 扩展未开启无法运行多进程示例\n);exit(1);}$workerNum4;// 子进程数$taskNum20;// 总任务数echoMaster PID: .getmypid().PHP_EOL;echoStart {$workerNum} workers, total {$taskNum} tasks.PHP_EOL;for($i0;$i$workerNum;$i){$pidpcntl_fork();if($pid-1){fwrite(STDERR,fork 失败\n);exit(1);}if($pid0){// 子进程逻辑$workerId$i;$myPidgetmypid();echo[Worker-{$workerId}] PID{$myPid} started\n;// 简单分片每个 worker 处理自己那份任务for($taskId$workerId;$taskId$taskNum;$taskId$workerNum){$startmicrotime(true);usleep(random_int(100,500)*1000);// 模拟 IO 阻塞100~500ms$cost(microtime(true)-$start)*1000;echo[Worker-{$workerId}] PID{$myPid} handle task{$taskId}, cost.(int)$cost.ms\n;}echo[Worker-{$workerId}] PID{$myPid} done\n;exit(0);}}// 主进程等待所有子进程结束while(pcntl_wait($status)0){}echoAll workers exited.\n;--- 代码2单进程协程模型Swoole ▎ 文件single_process_coroutine_demo.php ▎ 需要Swoole/OpenSwoole 扩展?php declare(strict_types1);/** * 单进程协程演示 * - 一个进程里开很多协程 * - 每个协程遇到 IO 等待时让出执行权 */if(!extension_loaded(swoole)){fwrite(STDERR,需要安装 swoole 或 openswoole 扩展\n);exit(1);}use Swoole\Coroutine;use Swoole\Coroutine\Channel;$taskNum20;$concurrency5;// 同时跑几个协程任务 Coroutine\run(function()use($taskNum,$concurrency){echoSingle Process PID: .getmypid().PHP_EOL;echoCoroutine concurrency{$concurrency}, total tasks{$taskNum}.PHP_EOL;$taskChannew Channel($taskNum);$doneChannew Channel($taskNum);// 投递任务for($i0;$i$taskNum;$i){$taskChan-push($i);}$taskChan-close();// 启动固定数量协程 workerfor($w0;$w$concurrency;$w){go(function()use($w,$taskChan,$doneChan){while(true){$taskId$taskChan-pop();if($taskIdfalse){break;}$startmicrotime(true);// 协程 sleep不会阻塞整个进程 Coroutine::sleep(random_int(100,500)/1000);$cost(microtime(true)-$start)*1000;echo[CoWorker-{$w}] task{$taskId}, cost.(int)$cost.ms\n;$doneChan-push(1);}});}// 等全部任务完成for($i0;$i$taskNum;$i){$doneChan-pop();}echoAll coroutine tasks done.\n;});--- 代码3最佳实践多进程 协程推荐 ▎ 文件best_practice_server.php ▎ 这是一个 HTTP 服务端 ▎ - 外层 worker_num 是多进程 ▎ - 每个 worker 内请求用协程并发处理?php declare(strict_types1);/** * 推荐模型多进程 协程 * 运行后 * php best_practice_server.php * 测试 *curlhttp://127.0.0.1:9501/?t0.3*/if(!extension_loaded(swoole)){fwrite(STDERR,需要安装 swoole 或 openswoole 扩展\n);exit(1);}$servernew Swoole\Http\Server(127.0.0.1,9501);$server-set([worker_num4, // 多进程4个 workermax_request10000, // 处理一定请求后重启 worker降低内存碎片风险enable_coroutinetrue, // 开启协程支持hook_flagsSWOOLE_HOOK_ALL, // 尽量把阻塞 IO hook 成协程 IO]);$server-on(Start,function(Swoole\Http\Server$server){echoHTTP server started at http://127.0.0.1:9501\n;echoMaster PID: {$server-master_pid}\n;});$server-on(WorkerStart,function(Swoole\Http\Server$server, int$workerId){echoWorkerStart worker_id{$workerId}, pid.posix_getpid().PHP_EOL;});$server-on(Request,function(Swoole\Http\Request$req, Swoole\Http\Response$res){$startmicrotime(true);$workerPidposix_getpid();$workerId$req-server[worker_id]?? -1;// 模拟外部 IO 时延秒$tisset($req-get[t])?(float)$req-get[t]:0.2;if($t0)$t0;if($t2)$t2;// 协程 sleep不会阻塞整个 worker Swoole\Coroutine::sleep($t);$cost(microtime(true)-$start)*1000;$res-header(Content-Type,application/json; charsetutf-8);$res-end(json_encode([oktrue,msgmulti-process coroutine,worker_id$workerId,worker_pid$workerPid,cost_ms(int)$cost,timedate(Y-m-d H:i:s),], JSON_UNESCAPED_UNICODE));});$server-start();--- 怎么跑Windows 重点说明 你当前环境是 Windows。pcntl 和大多数 Swoole 生产能力主要在 Linux/macOS 更常见。 最稳妥是用 WSL2 Ubuntu 跑 php-vphp-m|grep-Epcntl|swoole|openswoole没有扩展就装示例 peclinstallswoole# 或 openswoole--- 最后一句“选型落地” - 业务简单、团队偏传统先 FPM 多进程。 - 高并发 IO网关、长连接、实时服务上协程。 - 线上长期最优多进程做隔离协程做吞吐也就是上面第3份代码这条路。