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

php把运行时重构成常驻内存 + 多进程 + 事件驱动(Reactor) 模式完整流程=workerman

纯手写版不靠 Workerman/Swoole。 只用 PHP 自带能力pcntl_fork stream_socket_server stream_select实现你要的 常驻内存 多进程 Reactor 事件驱动 --- 一、先说目标大白话 把 PHP 从“脚本模式”改成“服务模式” - 脚本模式请求来一次PHP 启一次用完就死 - 服务模式进程长期活着反复处理请求 并发靠两层1. 多进程主进程 fork 多个 worker吃多核2. 事件驱动每个 worker 用 stream_select 盯很多连接谁有数据就处理谁 --- 二、目录结构 mini-reactor/ ├── server.php └── src/ ├── Master.php ├── Worker.php ├── Reactor.php ├── Http.php └── App.php --- 三、完整代码可直接跑1)src/Reactor.php?php namespace MiniReactor;class Reactor{private array$readStreams[];private array$readHandlers[];private bool$runningtrue;publicfunctionadd($stream, callable$handler): void{$id(int)$stream;stream_set_blocking($stream,false);$this-readStreams[$id]$stream;$this-readHandlers[$id]$handler;}publicfunctiondel($stream): void{$id(int)$stream;unset($this-readStreams[$id],$this-readHandlers[$id]);}publicfunctionstop(): void{$this-runningfalse;}publicfunctionrun(): void{while($this-running){if(!$this-readStreams){usleep(10000);continue;}$readarray_values($this-readStreams);$write[];$except[];$nstream_select($read,$write,$except,1);if($nfalse||$n0){continue;}foreach($readas$stream){$id(int)$stream;if(isset($this-readHandlers[$id])){($this-readHandlers[$id])($stream,$this);}}}}}---2)src/Http.php?php namespace MiniReactor;class HttpRequest{public string$methodGET;public string$path/;public array$query[];public array$headers[];public string$body;}class Http{public staticfunctionparse(string$raw): ?HttpRequest{$partsexplode(\r\n\r\n,$raw,2);$head$parts[0]??;$body$parts[1]??;$linesexplode(\r\n,$head);if(count($lines)1)returnnull;$startarray_shift($lines);if(!preg_match(#^([A-Z])\s(\S)\sHTTP/1\.[01]$#,$start,$m)){returnnull;}$reqnew HttpRequest();$req-method$m[1];$uri$m[2];$req-pathparse_url($uri, PHP_URL_PATH)?:/;parse_str(parse_url($uri, PHP_URL_QUERY)?:,$req-query);foreach($linesas$line){if(!str_contains($line,:))continue;[$k,$v]explode(:,$line,2);$req-headers[strtolower(trim($k))]trim($v);}$req-body$body;return$req;}public staticfunctionresponse(int$status, array$data): string{$reasonmatch($status){200OK,400Bad Request,404Not Found,500Internal Server Error, defaultOK,};$jsonjson_encode($data, JSON_UNESCAPED_UNICODE);$headers[HTTP/1.1 {$status} {$reason},Content-Type: application/json; charsetutf-8,Content-Length: .strlen($json),Connection: close,,$json];returnimplode(\r\n,$headers);}}---3)src/App.php?php namespace MiniReactor;class App{private int$bootAt;private int$counter0;// 常驻内存状态这个worker处理了多少请求 publicfunction__construct(){$this-bootAttime();}publicfunctionhandle(HttpRequest$req): array{$this-counter;if($req-path/ping){return[status200,body[code0,msgpong,pidgetmypid(),uptime_sectime()-$this-bootAt,handled$this-counter,]];}if($req-path/hello){$name$req-query[name]??world;return[status200,body[code0,datahello {$name},pidgetmypid(),handled$this-counter,]];}return[status404,body[code404,msgnot found,pidgetmypid(),handled$this-counter,]];}}---4)src/Worker.php?php namespace MiniReactor;class Worker{private$listenSocket;private Reactor$reactor;private App$app;private bool$stoppingfalse;publicfunction__construct($listenSocket){$this-listenSocket$listenSocket;$this-reactornew Reactor();$this-appnew App();// 常驻内存对象只初始化一次}publicfunctionrun(): void{pcntl_async_signals(true);pcntl_signal(SIGTERM,function(){$this-stoppingtrue;$this-reactor-stop();});pcntl_signal(SIGINT,function(){$this-stoppingtrue;$this-reactor-stop();});// 监听“有新连接”$this-reactor-add($this-listenSocket,function($serverSock, Reactor$reactor){$connstream_socket_accept($serverSock,0);if(!$conn)return;stream_set_blocking($conn,false);$buffer;// 监听“这个连接上有数据可读”$reactor-add($conn,function($client, Reactor$reactor)use($buffer){$chunkfread($client,8192);if($chunk||$chunkfalse){$reactor-del($client);fclose($client);return;}$buffer.$chunk;// 简化版读到头部结束就处理演示够用if(!str_contains($buffer,\r\n\r\n)){return;}$reqHttp::parse($buffer);if(!$req){fwrite($client, Http::response(400,[code400,msgbad request]));$reactor-del($client);fclose($client);return;}try{$ret$this-app-handle($req);$rawHttp::response($ret[status],$ret[body]);}catch(\Throwable$e){$rawHttp::response(500,[code500,msginternal error]);}fwrite($client,$raw);$reactor-del($client);fclose($client);});});echo[worker .getmypid().] started\n;$this-reactor-run();echo[worker .getmypid().] stopped\n;}}---5)src/Master.php?php namespace MiniReactor;class Master{private string$host;private int$port;private int$workerNum;private$listenSocket;private array$workers[];private bool$stoppingfalse;publicfunction__construct(string$host, int$port, int$workerNum){$this-host$host;$this-port$port;$this-workerNum$workerNum;}publicfunctionstart(): void{$errno0;$errstr;$contextstream_context_create([socket[so_reuseport1,backlog1024,]]);$this-listenSocketstream_socket_server(tcp://{$this-host}:{$this-port},$errno,$errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,$context);if(!$this-listenSocket){throw new\RuntimeException(listen failed: {$errstr}({$errno}));}stream_set_blocking($this-listenSocket,false);pcntl_async_signals(true);pcntl_signal(SIGINT, fn()$this-gracefulStop());pcntl_signal(SIGTERM, fn()$this-gracefulStop());pcntl_signal(SIGCHLD, fn()$this-reap());echo[master .getmypid().] listen {$this-host}:{$this-port}, workers{$this-workerNum}\n;for($i0;$i$this-workerNum;$i){$this-forkWorker();}while(!$this-stopping){sleep(1);}$this-shutdownAll();}privatefunctionforkWorker(): void{$pidpcntl_fork();if($pid0){throw new\RuntimeException(fork failed);}if($pid0){$workernew Worker($this-listenSocket);$worker-run();exit(0);}$this-workers[$pid]true;echo[master] fork worker {$pid}\n;}privatefunctionreap(): void{while(($pidpcntl_waitpid(-1,$status,WNOHANG))0){unset($this-workers[$pid]);echo[master] worker {$pid} exited\n;if(!$this-stopping){$this-forkWorker();// 自动补齐}}}privatefunctiongracefulStop(): void{$this-stoppingtrue;echo[master] stopping...\n;}privatefunctionshutdownAll(): void{foreach(array_keys($this-workers)as$pid){posix_kill($pid, SIGTERM);}while(count($this-workers)0){$this-reap();usleep(100000);}if(is_resource($this-listenSocket)){fclose($this-listenSocket);}echo[master] shutdown done\n;}}---6)server.php启动入口?php require_once __DIR__./src/Reactor.php;require_once __DIR__./src/Http.php;require_once __DIR__./src/App.php;require_once __DIR__./src/Worker.php;require_once __DIR__./src/Master.php;use MiniReactor\Master;$host0.0.0.0;$port8080;$cpu(int)trim(shell_exec(nproc 2/dev/null)?:4);$workerNummax(2,$cpu);$masternew Master($host,$port,$workerNum);$master-start();--- 四、怎么启动 php server.php 测试curlhttp://127.0.0.1:8080/pingcurlhttp://127.0.0.1:8080/hello?namejack你会看到 pid 变化说明请求被不同 worker 处理。 --- 五、完整流程超白话1. Master 启动并监听端口2. Master fork 出多个 Worker3. 每个 Worker 创建一个 Reactor 循环并常驻4. 有新连接时Reactor 收到“可读事件”5. accept 连接再监听这个连接的读事件6. 读到 HTTP 请求交给 App 处理7. 写回响应关闭连接8. 回到 Reactor 等下一波事件9. 某个 Worker 挂了Master 自动补一个 --- 六、这版是“自己写”的价值和边界 价值 - 你能完全理解底层模型不黑箱 - 任何框架Workerman/Swoole本质都能看懂 边界 这份代码是教学可运行版不是完整生产HTTP服务器。生产还要补 - Keep-Alive、分块传输、大包拆包、超时 - 连接限流、日志、监控、热重启 - 真正数据库连接池与慢查询保护 --- 一句话收尾 这份代码已经是纯手写的 PHP 常驻内存 多进程 Reactor 最小完整实现你可以直接在这个骨架上继续加协议细节和业务能力。

相关文章:

php把运行时重构成常驻内存 + 多进程 + 事件驱动(Reactor) 模式完整流程=workerman

纯手写版,不靠 Workerman/Swoole。只用 PHP 自带能力:pcntl_fork stream_socket_server stream_select,实现你要的:常驻内存 多进程 Reactor 事件驱动 …...

从CREO到URDF:机器人开发的终极自动化转换指南

从CREO到URDF:机器人开发的终极自动化转换指南 【免费下载链接】creo2urdf Generate URDF models from CREO mechanisms 项目地址: https://gitcode.com/gh_mirrors/cr/creo2urdf 在机器人设计与仿真领域,从CAD模型到仿真环境的转换一直是制约开发…...

Appium Inspector进阶玩法:除了看元素,这些隐藏功能让你的测试效率翻倍

Appium Inspector进阶玩法:除了看元素,这些隐藏功能让你的测试效率翻倍 如果你已经熟悉Appium Inspector的基础功能——查看元素、获取属性、验证定位策略,那么是时候解锁它的隐藏技能了。这款工具远不止是一个简单的元素查看器,…...

WinAppDriver环境搭建避坑大全:解决.NET依赖、版本冲突和‘找不到元素’的常见问题

WinAppDriver实战避坑指南:从环境搭建到元素定位的深度解决方案 Windows桌面应用自动化测试领域,WinAppDriver作为微软官方推出的测试框架,正逐渐成为企业级自动化测试的首选方案。但在实际项目落地过程中,开发者们常会遇到各种&…...

LLM自我进化:基于自我博弈与DPO的AI能力提升框架

1. 项目概述:当AI开始“思考”自己的进化最近在开源社区里,一个名为czhou578/llm-god的项目引起了我的注意。这个名字本身就充满了哲学意味——“LLM之神”。它不是一个简单的模型微调工具,也不是一个应用框架,而是一个试图让大型…...

点云补全技术:原理、方法与应用场景解析

1. 点云补全技术概述点云补全技术是计算机视觉和三维重建领域的重要研究方向,它致力于解决现实场景中由于遮挡、传感器限制或物体材质导致的点云数据缺失问题。想象一下用激光雷达扫描一辆汽车时,车身某些部位会因为角度问题无法被完整捕捉,这…...

零样本3D点云补全技术LaS-Comp原理与实践

1. 项目背景与核心价值去年在CVPR上看到一篇关于3D形状补全的论文时,我正为一个工业检测项目头疼——产线上扫描的零件点云总是存在缺失。传统方法要么需要大量配对数据训练,要么补全结果扭曲变形。直到发现LaS-Comp这个框架,才意识到零样本学…...

配置中心选型生死局:对比Nacos/Consul/Etcd/Apollo在Python生态中的启动延迟、内存开销、TLS握手耗时与Leader选举收敛时间(实测数据表已附)

更多请点击: https://intelliparadigm.com 第一章:Python分布式配置的核心挑战与选型逻辑 在微服务与云原生架构普及的今天,Python应用常以多实例、跨环境(开发/测试/生产)、多集群方式部署。此时,硬编码配…...

5分钟掌握Windows安卓应用无缝运行方案

5分钟掌握Windows安卓应用无缝运行方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 想在Windows电脑上直接运行安卓应用,却厌倦了臃肿模拟器的漫长等待&…...

【工业级Python 3D管线优化白皮书】:基于NVIDIA Nsight+py-spy双工具链的CPU-GPU异步流水线调优实录(仅限首批200位开发者获取)

更多请点击: https://intelliparadigm.com 第一章:Python 3D管线优化的工业级挑战与范式演进 在工业级三维可视化与仿真系统中,Python 并非传统首选语言,但其生态(如 PyVista、trimesh、Open3D 和 Blender Python AP…...

TiViBench:视频生成模型的视觉推理评估系统

1. 项目概述TiViBench是一个专门用于评估视频生成模型视觉推理能力的层次化基准测试系统。随着视频生成技术的快速发展,模型已经从单纯追求视觉合理性逐步转向需要具备物理合理性和逻辑一致性的高级任务。然而,现有评估方法主要关注视觉保真度和时间连贯…...

Octogen:让AI代理原生操作数据库,实现自然语言数据查询与分析

1. 项目概述:当数据库遇上AI代理 如果你最近在关注AI应用开发,特别是那些能自主处理复杂任务的智能代理(Agent),那你大概率听说过LangChain、AutoGPT或者CrewAI这些框架。它们让AI不再只是简单地回答一个问题&#xff…...

通过 curl 命令快速测试 Taotoken 大模型 API 的连通性与响应

通过 curl 命令快速测试 Taotoken 大模型 API 的连通性与响应 1. 准备工作 在开始测试之前,请确保已获取有效的 Taotoken API Key。登录 Taotoken 控制台,在「API 密钥」页面创建或复制现有密钥。同时确认已安装 curl 工具,大多数 Linux/ma…...

Olmo 3开源大模型:技术架构与实战应用解析

1. 项目背景与核心价值 Olmo 3作为新一代开放语言模型家族,正在重新定义AI领域的协作边界。这个由艾伦人工智能研究所(AI2)主导的项目,从训练代码、数据集到模型权重全面开源,堪称目前开放程度最高的大语言模型解决方案…...

Transformer特征注入性问题与SIPIT算法解析

1. Transformer架构中的注入性问题剖析在自然语言处理领域,Transformer模型因其卓越的并行计算能力和长距离依赖捕捉特性,已成为各类NLP任务的基础架构。但在实际应用中,研究者们发现模型存在一个关键缺陷——不同层级的特征表示会相互干扰&a…...

使用 curl 命令直接测试 Taotoken 大模型 API 的连通性与响应

使用 curl 命令直接测试 Taotoken 大模型 API 的连通性与响应 1. 准备工作 在开始测试之前,请确保您已具备以下条件: 有效的 Taotoken API Key,可在 Taotoken 控制台的「API 密钥」页面创建目标模型 ID,可在 Taotoken 模型广场…...

NextChat开源AI助手聚合平台:多模型统一接入与私有化部署实战

1. 项目概述与核心价值 如果你和我一样,每天需要和多个AI模型打交道——可能是用GPT-4o处理代码,用Claude分析长文档,再用DeepSeek查询一些本地知识——那么你一定也厌倦了在浏览器里开无数个标签页,或者在多个独立应用之间来回切…...

Switch大气层整合包:5分钟打造专属游戏世界的终极指南

Switch大气层整合包:5分钟打造专属游戏世界的终极指南 【免费下载链接】Atmosphere-stable 大气层整合包系统稳定版 项目地址: https://gitcode.com/gh_mirrors/at/Atmosphere-stable 想彻底释放你的Switch游戏机潜能吗?大气层整合包是目前最稳定…...

faster_whisper,视频转文字,并生成字幕文件

faster_whisper,视频转文字,并生成字幕文件(附带exe) 使用说明: –model:选 tiny/base/small/medium/large(越大越准、越耗资源)。 模型路径(medium):C:\Users\XXX.cache…...

使用 OpenClaw 配置 Taotoken 实现自动化工作流

使用 OpenClaw 配置 Taotoken 实现自动化工作流 1. 自动化工作流中的多模型集成需求 在构建智能体工作流时,开发者常需要灵活调用不同的大模型能力。传统方式需要为每个模型单独维护 API 密钥和接入点,这增加了系统复杂度和维护成本。Taotoken 提供的统…...

你的效率革命:为什么这款跨平台桌面待办工具值得一试?

你的效率革命:为什么这款跨平台桌面待办工具值得一试? 【免费下载链接】My-TODOs A cross-platform desktop To-Do list. 跨平台桌面待办小工具 项目地址: https://gitcode.com/gh_mirrors/my/My-TODOs 你是否经常被各种任务搞得焦头烂额&#xf…...

AO3镜像站终极指南:3分钟快速访问全球同人创作宝库

AO3镜像站终极指南:3分钟快速访问全球同人创作宝库 【免费下载链接】AO3-Mirror-Site 项目地址: https://gitcode.com/gh_mirrors/ao/AO3-Mirror-Site Archive of Our Own(AO3)镜像站是专为中文用户设计的免费访问解决方案&#xff0…...

免费音频编辑神器Audacity:5分钟搞定专业级音频处理的完整指南

免费音频编辑神器Audacity:5分钟搞定专业级音频处理的完整指南 【免费下载链接】audacity Audio Editor 项目地址: https://gitcode.com/GitHub_Trending/au/audacity 您是否曾为音频中的杂音烦恼?是否羡慕专业录音棚的清晰音质?现在…...

Fomu FPGA开发板入门:从Verilog到RISC-V软核的渐进式学习指南

1. 从零开始:认识你的Fomu硬件开发板如果你对FPGA(现场可编程门阵列)感兴趣,但又觉得它高深莫测、入门门槛太高,那么Fomu这个小玩意儿可能会彻底改变你的看法。它是一块可以塞进USB接口的FPGA开发板,把整个…...

Windows安卓应用安装革命:APK Installer轻量级解决方案深度解析

Windows安卓应用安装革命:APK Installer轻量级解决方案深度解析 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer APK Installer是一款专为Windows系统设计的…...

Audacity音频编辑框架:从信号处理到现代架构的技术演进

Audacity音频编辑框架:从信号处理到现代架构的技术演进 【免费下载链接】audacity Audio Editor 项目地址: https://gitcode.com/GitHub_Trending/au/audacity Audacity作为开源音频编辑软件的标杆,其技术架构的演进历程反映了音频处理领域从传统…...

YaeAchievement:3分钟完成原神成就数据一键导出,告别繁琐手动记录

YaeAchievement:3分钟完成原神成就数据一键导出,告别繁琐手动记录 【免费下载链接】YaeAchievement 更快、更准的原神数据导出工具 项目地址: https://gitcode.com/gh_mirrors/ya/YaeAchievement 还在为整理原神上千个成就而烦恼吗?每…...

深度解密:如何用CyberpunkSaveEditor逆向工程《赛博朋克2077》存档系统

深度解密:如何用CyberpunkSaveEditor逆向工程《赛博朋克2077》存档系统 【免费下载链接】CyberpunkSaveEditor A tool to edit Cyberpunk 2077 sav.dat files 项目地址: https://gitcode.com/gh_mirrors/cy/CyberpunkSaveEditor CyberpunkSaveEditor是一款基…...

新手友好:通过快马生成的代码理解智能车避障算法基本原理

新手友好:通过快马生成的代码理解智能车避障算法基本原理 作为一个刚接触智能车领域的新手,我最近在InsCode(快马)平台上体验了一个非常有趣的智能车避障算法模拟项目。这个项目特别适合像我这样的初学者,因为它用Python模拟了一个二维平面上…...

Cursor Free VIP终极指南:三步解锁AI编程助手完整功能

Cursor Free VIP终极指南:三步解锁AI编程助手完整功能 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tri…...