尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PHP运行时的术语大全的庖丁解牛

PHP运行时的术语大全的庖丁解牛 PHP运行时术语大全的庖丁解牛总纲PHP运行时 Zend引擎内核 SAPI接口层 扩展层 用户态业务层。SAPI是关键不同SAPI对应不同运行模式FPM、CLI、CGI直接决定整套运行时行为、生命周期、内存模型。区分两大运行时形态请求隔离型FPM、常驻内存型Swoole‑CLI/Hyperf。一、SAPI 层术语最顶层入口SAPIServer Application Programming Interface服务器应用程序编程接口根因Zend引擎本身不负责接收HTTP、不处理网络SAPI是PHP对外的接入层给Zend引擎喂入输入、输出结果。不同SAPI生命周期完全不一样。常见SAPIfpm‑fpmFPM Web运行模式cli命令行脚本cgi原始CGIapache2handler老版本Apache mod_phpswooleSwoole自定义SAPICLI下实现常驻服务核心PHP本身没有Web能力全部靠SAPI实现网络/命令行交互。SG(server_globals)SAPI全局结构体保存请求相关全局信息$_SERVER、请求头、输入输出缓冲区、请求状态。FPM每请求重置Swoole不能直接复用SG改用协程上下文保存请求信息。PG(core_globals)PHP全局配置对应php.ini各项配置进程级别整个进程生命周期有效。请求生命周期Request lifecycleFPM‑SAPI生命周期请求隔离请求到来 → 初始化PHP环境 → 执行用户代码 → 请求关闭阶段RSHUTDOWN → 释放请求资源 → Worker进程不退出等待下一个请求进程存活请求级资源全部销毁。CLI普通脚本生命周期脚本启动 → 执行全部代码 → 脚本结束整个进程销毁退出Swoole‑CLI常驻运行时进程启动BOOT初始化仅一次→ 循环事件循环每来一个请求新建协程协程结束销毁协程资源进程本身永不退出RINIT / RSHUTDOWN 请求初始化/请求关闭RINIT每一次请求到来执行加载ini、超全局变量、GET/_GET/G​ET/_POST。FPM每次请求都会跑RINIT。RSHUTDOWN请求结束回调做请求资源清理。Hyperf/Swoole常驻模式不会自动执行RINIT/RSHUTDOWN需要框架自己模拟请求生命周期。GINIT / GSHUTDOWN 全局初始化/全局关闭进程启动执行一次进程销毁执行一次。常驻内存框架业务初始化放在GINIT阶段。二、Zend VM 虚拟机核心术语ZendVM 虚拟机PHP的执行引擎不直接执行源码执行编译后的Opcode字节码。工作流PHP源码 → 编译为Opcode → ZendVM逐条解释执行。Opcode操作码编译生成的指令类似汇编ZEND_ADD、ZEND_ECHO等。OPcache缓存Opcode跳过重复编译。OPcache字节码缓存扩展把编译好的Opcode存共享内存多个FPM Worker共享避免每次请求编译源码消耗CPU。opcache.validate_timestamps开启会检测php文件修改生产关闭修改代码不自动生效。opcache.revalidate_freq文件检查周期。Zval 内核变量结构体PHP所有变量底层统一结构。成员value存储实际数据、u1type类型、refcount__gc引用计数、is_ref__gc是否引用。PHP一切变量都是zvalint string array object resource。refcount 引用计数根因PHP内存管理基础。记录这个zval被多少变量引用refcount降到0内存释放。缺陷循环引用对象/数组refcount无法自动回收需要GC回收器。GC 垃圾回收器循环引用回收专门处理$a$b; $b$a这种循环引用达到gc_threshold阈值触发GC扫描回收。代价会消耗CPU大对象多的时候会出现STWstop‑the‑world停顿。COW 写时复制 Copy‑On‑Write根因节省内存。数组赋值$b $a不拷贝内存refcount1共用同一份zval只有发生修改时才真正复制内存。坑大数组传参函数内部修改数组触发拷贝内存瞬间飙升。符号表(Symbol table)存储变量名到zval的映射分全局符号表、局部函数符号表。全局符号表$GLOBALSFPM每次请求重置Swoole常驻进程全局符号表进程级别协程并发极易污染。EG(executor_globals)执行器全局Zend执行器上下文保存调用栈、异常、错误处理、当前符号表。调用栈(Call stack)函数/方法一层层调用形成栈帧异常回溯、debug_backtrace读取调用栈。栈帧(zend_execute_data)每一次函数调用生成一个栈帧保存局部变量、返回地址。函数执行结束栈帧销毁。三、变量、超全局、资源类型术语超全局变量 $_GET $_POST $_COOKIE $_SESSION $_SERVER $_REQUEST $_FILESFPMRINIT阶段每请求重新生成请求隔离。Swoole/Hyperf禁止直接使用超全局变量多个协程共享进程全局会发生数据错乱框架封装Request对象从协程上下文拿数据。Resource资源类型内核外部句柄mysql连接、文件句柄、socket句柄。资源是编号不是真正指针请求结束FPM自动回收释放Swoole常驻不会自动回收必须手动close。静态变量 static $a函数内static变量作用域是进程级别。FPM同一个Worker多次请求之间static变量保留值Swoole所有协程共享这个static变量极易并发错乱。全局变量 global $a存放在全局符号表进程存活期间保留常驻内存风险极高。对象句柄(Object handle)PHP对象不直接拷贝变量存对象编号多个变量指向同一个对象实例。四、错误、异常、运行时配置术语error_reporting 错误报告级别控制哪些级别错误会被抛出E_ERROR、E_WARNING、E_NOTICE、E_DEPRECATED。display_errors是否把错误打印输出到页面生产环境必须关闭。log_errors错误写入日志文件线上开启。Exception 异常对象主动throw抛出try‑catch捕获。Error致命错误PHP7之后大部分致命错误转为Error异常可以捕获。zend错误处理回调 set_error_handler、set_exception_handler接管错误、异常框架用来统一记录日志。注意部分致命错误无法捕获。php.iniPHP运行时配置文件。FPM可以通过pool的php_value/php_admin_value覆盖CLI/Swoole启动时读取一份php.ini运行时修改部分配置不生效。ini_set()运行时修改ini配置部分配置受PHP_INI_*模式限制运行时不可修改。PHP_INI_ALL代码可修改PHP_INI_PERDIRphp.ini、.htaccess可改代码不可改PHP_INI_SYSTEM仅php.ini可修改五、两大SAPI运行时模型对比核心考点模型1FPM‑SAPI请求隔离运行时Worker进程常驻但是每一次请求执行完整RINIT、RSHUTDOWN请求结束请求级符号表、局部变量、资源全部释放但是进程级静态变量、全局变量在同一个Worker内跨请求保留没有用户态协程一个进程同一时刻只能处理1个请求无内置连接池数据库、redis连接属于请求资源请求结束关闭坑点很多人误以为FPM每次请求销毁进程只是销毁请求资源进程本身复用。模型2Swoole‑CLI常驻内存运行时Hyperf底层进程启动执行一次GINIT永远不会自动执行RINIT/RSHUTDOWN没有天然的请求隔离全部请求/协程跑在同一个进程空间。协程上下文模拟请求隔离进程全局符号表、static静态变量对所有协程可见。对象、连接、数组不会请求结束自动清空容易内存泄漏、协程污染。需要框架手动管理资源defer归还连接、协程退出清理上下文。坑直接使用GET/_GET/G​ET/_POST/global/static变量会出现协程数据错乱。六、扩展与钩子运行时术语PHP扩展ExtensionC语言编写编译进PHP分为内核扩展pdo、curl、第三方扩展swoole、redis。扩展可以修改ZendVM行为注册函数、钩子。Zend钩子Zend hook内核回调钩子opcode执行钩子、函数调用钩子AOP、调试工具基于内核钩子实现。opcache预加载 opcache.preloadPHP7.4常驻内存预加载进程启动把类一次性加载到内存不用autoload适合Swoole项目。autoload自动加载类找不到时触发__autoload/composer自动加载FPM每次请求会触发Swoole启动阶段全部加载完成运行时几乎不再触发。__construct / __destruct 析构函数对象销毁时触发FPM请求结束批量触发Swoole常驻内存对象不释放析构不会跑。七、运行时故障坑点术语高频请求级资源泄漏 vs 进程级内存泄漏请求级单次请求内部内存大RSHUTDOWN后释放FPM不怕进程级static数组无限追加、全局变量不断堆数据内存只涨不跌FPM靠max_requests重启缓解Swoole风险极高。循环引用内存泄漏对象互相引用refcount无法降为0等待GCGC不触发内存一直占用。写时复制陷阱大数组传参函数内部修改触发COW复制内存瞬间翻倍。超全局变量污染Swoole特有直接使用$_GET $_POST协程并发互相覆盖数据。静态变量跨协程污染函数static变量所有协程共享并发请求数据错乱。RSHUTDOWN缺失Swoole没有原生RSHUTDOWN资源不会自动回收连接、文件句柄忘记关闭持续泄漏。OPcache失效问题FPM开发环境忘记开启opcache.validate_timestamps改代码看不到效果。STW停顿GC大规模回收循环引用对象ZendVM暂停执行所有PHP代码出现请求卡顿。八、FPM运行时 vs Swoole常驻运行时对照表运行时维度FPM‑SAPISwoole‑CLI常驻内存RINIT/RSHUTDOWN每请求自动执行不会自动执行框架模拟全局符号表每请求重置进程全局所有协程共享static静态变量同Worker跨请求保留全部协程共享高并发危险超全局$_GET每请求重建安全原生超全局不可直接使用对象/资源回收RSHUTDOWN自动回收请求资源不会自动回收需要手动释放Opcode加载每请求autoloadOPcache缓存进程启动一次性全部加载内存泄漏缓解手段pm.max_requests定期重启Worker无自动机制代码层面管控
返回列表