当前位置: 首页 > news >正文

php方案 原生协程支持(Fiber最佳实践完整的

PHP Fiber 协程完整最佳实践---一、Fiber 基础原理 传统 PHP:同步阻塞 ┌─────────────────────────────┐ │ 请求1→ 执行 → 等IO → 完成 │ 进程被占用 └─────────────────────────────┘ Fiber 协程:协作式多任务 ┌──────────────────────────────────────┐ │ Fiber1 执行 → 挂起 → Fiber2 执行 │ │ Fiber2 挂起 → Fiber1 恢复 → 完成 │ 同一进程 └──────────────────────────────────────┘---二、Fiber 核心 API<?php// Fiber 生命周期$fiber=newFiber(function():string{echo"1. Fiber 开始\n";$value=Fiber::suspend('第一次挂起');// 挂起,返回值给外部echo"3. 恢复,收到: {$value}\n";Fiber::suspend('第二次挂起');echo"5. 再次恢复\n";return'最终返回值';});$result1=$fiber->start();// 启动,运行到第一个 suspendecho"2. 外部收到: {$result1}\n";$result2=$fiber->resume('hello');// 恢复,传值给 Fiberecho"4. 外部收到: {$result2}\n";$fiber->resume();// 最终恢复echo"6. Fiber 完成: ".$fiber->getReturn()."\n";// 输出:// 1. Fiber 开始// 2. 外部收到: 第一次挂起// 3. 恢复,收到: hello// 4. 外部收到: 第二次挂起// 5. 再次恢复// 6. Fiber 完成: 最终返回值---三、状态检查<?php $fiber=newFiber(function():void{Fiber::suspend();});var_dump($fiber->isStarted());// falsevar_dump($fiber->isSuspended());// falsevar_dump($fiber->isRunning());// falsevar_dump($fiber->isTerminated());// false$fiber->start();var_dump($fiber->isStarted());// truevar_dump($fiber->isSuspended());// truevar_dump($fiber->isTerminated());// false$fiber->resume();var_dump($fiber->isTerminated());// true---四、事件循环(核心模式)<?php// 简单事件循环实现classEventLoop{private array $fibers=[];private array $timers=[];publicfunctionadd(Fiber $fiber):void{$this->fibers[]=$fiber;}publicfunctionaddTimer(float $delay,callable $callback):void{$this->timers[]=['at'=>microtime(true)+$delay,'callback'=>$callback,];}publicfunctionrun():void{// 启动所有 Fiberforeach($this->fibers as $fiber){if(!$fiber->isStarted()){$fiber->start();}}// 循环调度while($this->hasPending()){// 处理定时器$now=microtime(true);foreach($this->timers as $key=>$timer){if($now>=$timer['at']){($timer['callback'])();unset($this->timers[$key]);}}// 恢复挂起的 Fiberforeach($this->fibers as $key=>$fiber){if($fiber->isSuspended()){$fiber->resume();}if($fiber->isTerminated()){unset($this->fibers[$key]);}}usleep(1000);// 1ms 轮询间隔}}privatefunctionhasPending():bool{return!empty($this->fibers)||!empty($this->timers);}}// 使用$loop=newEventLoop();$loop->add(newFiber(function():void{echo"任务A 开始\n";Fiber::suspend();// 模拟等待echo"任务A 完成\n";}));$loop->add(newFiber(function():void{echo"任务B 开始\n";Fiber::suspend();echo"任务B 完成\n";}));$loop->run();// 任务A 开始// 任务B 开始// 任务A 完成// 任务B 完成---五、模拟异步 HTTP 请求<?php// 用 Fiber 模拟并发 HTTP 请求classAsyncHttpClient{private EventLoop $loop;publicfunction__construct(EventLoop $loop){$this->loop=$loop;}publicfunctionget(string $url):Fiber{$fiber=newFiber(function()use($url):string{// 非阻塞 socket$context=stream_context_create(['http'=>['timeout'=>5]]);$host=parse_url($url,PHP_URL_HOST);$path=parse_url($url,PHP_URL_PATH)?:'/';$socket=stream_socket_client("tcp://{$host}:80",$errno,$errstr,5,STREAM_CLIENT_CONNECT|STREAM_CLIENT_ASYNC_CONNECT);stream_set_blocking($socket,false);// 发送请求fwrite($socket,"GET {$path} HTTP/1.1\r\nHost: {$host}\r\nConnection: close\r\n\r\n");// 挂起等待响应Fiber::suspend($socket);// 恢复后读取响应$response='';while(!feof($socket)){$response.=fread($socket,8192);}fclose($socket);return$response;});return$fiber;}}---六、生产级调度器<?php classScheduler{private \SplQueue $ready;private array $suspended=[];publicfunction__construct(){$this->ready=new\SplQueue();}publicfunctionspawn(callable $task):void{$fiber=newFiber($task);$this->ready->enqueue($fiber);}publicfunctionrun():void{while(!$this->ready->isEmpty()){$fiber=$this->ready->dequeue();try{if(!$fiber->isStarted()){$value=$fiber->start();}elseif($fiber->isSuspended()){$value=$fiber->resume();}// 如果还没结束,重新入队if(!$fiber->isTerminated()){$this->ready->enqueue($fiber);}}catch(\Throwable $e){echo"Fiber 异常: ".$e->getMessage()."\n";}}}}// 使用$scheduler=newScheduler();$scheduler->spawn(function():void{for($i=0;$i<3;$i++){echo"任务1: step {$i}\n";Fiber::suspend();// 主动让出控制权}});$scheduler->spawn(function():void{for($i=0;$i<3;$i++){echo"任务2: step {$i}\n";Fiber::suspend();}});$scheduler->run();// 任务1: step 0// 任务2: step 0// 任务1: step 1// 任务2: step 1// 任务1: step 2// 任务2: step 2---七、异常处理<?php $fiber=newFiber(function():void{try{echo"Fiber 运行中\n";Fiber::suspend();echo"Fiber 恢复\n";}catch(\Exception $e){echo"Fiber 内部捕获: ".$e->getMessage()."\n";}});$fiber->start();// 向 Fiber 内部抛出异常$fiber->throw(new\Exception('外部注入的异常'));// 输出:Fiber 内部捕获: 外部注入的异常---八、与 ReactPHP 集成(生产推荐)<?php// composer require react/event-loop react/http react/promiseuse React\EventLoop\Loop;use React\Promise\Promise;// ReactPHP 已内置 Fiber 支持(v3+)$loop=Loop::get();// 将 Promise 转为 Fiber 可等待functionawait(Promise $promise):mixed{$fiber=Fiber::getCurrent();$result=null;$error=null;$promise->then(function($value)use($fiber,&$result):void{$result=$value;$fiber->resume($value);},function($reason)use($fiber,&$error):void{$error=$reason;$fiber->throw($reasoninstanceof\Throwable?$reason:new\RuntimeException((string)$reason));});returnFiber::suspend();}// 使用$fiber=newFiber(function()use($loop):void{// 模拟异步等待$promise=newPromise(function($resolve)use($loop):void{$loop->addTimer(1.0,fn()=>$resolve('数据加载完成'));});$result=await($promise);echo $result."\n";});$fiber->start();$loop->run();---九、数据库异步查询<?php// 用 Fiber 包装同步数据库查询,实现伪并发classAsyncDatabase{private \PDO $pdo;private Scheduler $scheduler;publicfunction__construct(\PDO $pdo,Scheduler $scheduler){$this->pdo=$pdo;$this->scheduler=$scheduler;}publicfunctionquery(string $sql,array $params=[]):mixed{// 挂起当前 Fiber,让其他任务先跑Fiber::suspend();$stmt=$this->pdo->prepare($sql);$stmt->execute($params);return$stmt->fetchAll();}}// 并发查询示例$scheduler=newScheduler();$scheduler->spawn(function()use($db):void{$users=$db->query('SELECT * FROM users LIMIT 10');echo"用户数: ".count($users)."\n";});$scheduler->spawn(function()use($db):void{$orders=$db->query('SELECT * FROM orders LIMIT 10');echo"订单数: ".count($orders)."\n";});$scheduler->run();// 两个查询交替执行---十、Fiber vs 其他方案对比 ┌───────────────┬──────────┬─────────────┬──────────┬────────────┐ │ 特性 │ Fiber │ Swoole 协程 │ ReactPHP │ 传统多进程 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ 需要扩展 │ 否 │ 是 │ 否 │ 否 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ 真正非阻塞 IO │ 否 │ 是 │ 是 │ 否 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ 学习成本 │ 低 │ 高 │ 中 │ 低 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ 生产成熟度 │ 中 │ 高 │ 高 │ 高 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ PHP 版本要求 │8.1+│ 任意 │ 任意 │ 任意 │ ├───────────────┼──────────┼─────────────┼──────────┼────────────┤ │ 适合场景 │ 框架底层 │ 高并发服务 │ 异步应用 │ 简单并发 │ └───────────────┴──────────┴─────────────┴──────────┴────────────┘---十一、最佳实践原则1.Fiber 不是银弹 └── 不能解决真正的 IO 阻塞(需配合非阻塞 IO)2.适合用 Fiber 的场景 ├── 框架中间件管道 ├── 生成器替代方案 ├── 协作式任务调度 └── 异步库的底层实现3.不适合直接用 Fiber 的场景 ├── 高并发 HTTP 服务 → 用 Swoole ├── 真正异步 IO → 用 ReactPHP/Amp └── 简单脚本 → 直接同步4.生产推荐组合 └── Fiber+ReactPHP v3 或 Fiber+Amp v3---推荐学习路径 Fiber 基础 → 事件循环原理 → ReactPHP/Amp → Swoole 协程 ↓ ↓ ↓ ↓ 理解挂起 理解调度机制 生产异步应用 高性能服务
http://www.jsqmd.com/news/855625/

相关文章:

  • RHEL9.6虚拟机安装配置攻略————安装虚拟机
  • LLM结构化输出工程:让模型输出你真正需要的格式
  • 【Perplexity天文知识搜索终极指南】:20年天体物理工程师亲授5大避坑法则与实时星图调用技巧
  • MTP:大模型推理提速黑科技(Multi-Token Prediction)
  • 告别HDR格式混乱:用Python代码实战HLG与PQ曲线互转(附完整代码)
  • Windows Phone Internals深度解析:3层技术架构解锁Lumia设备的完整方案
  • 软件工程师在智能体视觉时代的机遇(19)
  • 【量化】Vision Transformer 的完全量化已经从简单的 CNN 方法移植,发展成为一个拥有丰富技术体系的独立研究方向:综述
  • 3种方法彻底解锁英雄联盟国服皮肤:R3nzSkin换肤工具完整指南
  • LTE/5G常见业务问题(比如速率低 /MOS<3/随机接入失败等 )排查思路和方法
  • 告别拓展坞!实测Spacedesk无线投屏:Win10/Win11到iPad的延迟、画质与触控体验全解析
  • 期刊推荐:SN Social Sciences(ISSN: 2662-9283)
  • 告别DHCP:ESXi 8.0安装后如何手动配置静态IP和管理网络
  • IPC如何查看照片缩略图及照片
  • Dify系列课程 - 6.本地Dify关联本地大模型 Deepseek
  • 13 极物科技 JetLinks MQTT:网关设备与网关子设备 - 温控设备场景
  • c#软件开发学习笔记--数据类型
  • 保姆级教程:从VMnet感叹号到CentOS网络‘被拔出’,一站式修复VMware虚拟网络所有问题
  • 笔记本散热革命:NBFC-Linux让你的电脑告别“烧烤模式“[特殊字符]
  • Vibe Coding工作流2026:AI辅助编程的真实使用方式
  • Amphenol ICC MSPEC2L0A5010线束组件解析与替代思路
  • 深入解析Android架构设计:聚焦MVVM模式及其应用实践
  • RS-WorldModel: a Unified Model for RemoteSensing Understanding and Future SenseForecasting
  • NGA论坛优化脚本完整指南:5分钟打造高效浏览体验
  • 为什么你的微调模型Perplexity下降23%但人工测评反降41%?——揭开评估失真背后的4层认知断层
  • 从宿舍查寝神器到企业考勤解决方案:栎偲考勤神器的技术落地实践
  • 部署安装CLup(6.0版本-超详细)
  • 华为、华三、思科、锐捷网络设备远程登录配置
  • 5.20学习内容
  • Android 音视频开发深度解析:从基础原理到面试实战