Webman的php start.php reload仅重载onMessage等回调中动态require的代码,不重载类定义、配置数组、OPcache缓存及预加载逻辑;生效需验证PID变化或日志新记录。

Webman 的 php start.php reload 能实现不停机更新,但仅限于特定代码路径;改了控制器类、配置数组或用了 OPcache,reload 就不会生效——这不是 bug,是机制设计使然。
reload 为什么只重载 onMessage 里的 require 文件?
Webman(底层是 Workerman)的 reload 本质是向主进程发 SIGUSR1,主进程再逐个通知 Worker 子进程“处理完当前请求后退出”,同时拉起新 Worker 进程。新进程会重新执行整个启动流程,但关键点在于:只有在运行时动态加载的 PHP 代码才会被重新解析。
-
onWorkerStart中一次性require的配置文件、$config = ['host' => 'old'];这类变量赋值,reload 后仍是旧值——因为新 Worker 进程虽然重启了,但这段逻辑仍按原样执行一遍,没做差异判断 -
onMessage或onRequest回调里用require './app/logic/v2.php'加载业务文件,reload 后新 Worker 会重新走这行代码,从而加载新内容 - Composer 自动加载的类(如
app/controller/Api.php)不受 reload 影响——类定义一旦被class_exists()或首次实例化触发加载,就固化在内存里,reload 不会重新include_once它
OPcache 是 reload 失效最常见原因
PHP CLI 模式下若开启 opcache.enable_cli=1(很多生产环境默认开启),即使 reload 启动了新 Worker 进程,PHP 解释器仍从 OPcache 中读取旧字节码,新 PHP 文件根本没被编译执行。
- 临时验证:用
php -d opcache.enable_cli=0 start.php reload测试,如果这时接口返回新结果,基本可锁定是 OPcache 导致 - 长期方案:在
php.ini中设opcache.revalidate_freq=0(每次检查文件修改时间),或直接关掉opcache.enable_cli=0 - 注意:Webman 的
config/bootstrap.php或webman\support\Bootstrap预加载机制也受 OPcache 影响,这些代码在 Worker 初始化阶段就执行完毕,reload 不会重跑
哪些情况必须用 restart 而不是 reload?
php start.php restart 是先 stop 再 start,会中断服务几秒,但它能彻底清空所有进程状态和缓存,适用于 reload 无能为力的场景。
立即学习“PHP免费学习笔记(深入)”;
- 修改了
start.php中 Worker 构造参数,比如$worker->count、监听端口、SSL 配置等——这些由主进程控制,reload 不重建主进程 - 变更了类定义、
const、define()、静态属性或 trait 实现——这些符号已加载进内存,只有重启整个 PHP 进程才能刷新 - 启用了 Monitor 进程自动重启(
'enable_file_monitor'=>true),它监听文件变更时发的是SIGINT,不是SIGUSR1,会导致强制终止 Worker,不保证请求完成,**生产环境应禁用**
怎么确认 reload 真的生效了?
别信终端输出的 Reload success,那是主进程收到信号后的响应,不代表 Worker 已更新。
- 查进程 PID:
php start.php status输出中,对比 reload 前后各 Worker 的 PID 是否变化;没变说明没真正重启 - 看日志时间戳:
tail -f runtime/log/worker.log,搜索worker#0 started,新记录的时间是否与 reload 操作时间接近 - 加调试输出:在
onWorkerStart里写file_put_contents('/tmp/reload.log', date('Y-m-d H:i:s') . " worker#{$worker->id}\n", FILE_APPEND);,观察 reload 后是否有新时间戳写入
真正的平滑更新,依赖你把可变逻辑“推到运行时”——比如把配置从 onWorkerStart 搬到 onRequest 中按需加载,把类实例化延迟到请求上下文里,而不是在进程初始化阶段就固化下来。



















