Worker进程平滑重启本质是主进程逐个替换旧Worker,新进程必须在onWorkerStart中动态加载代码才生效;若文件在全局或Server初始化时加载、OPcache未失效、模式选错(如SWOOLE_BASE)、或配置项(如worker_num)被修改,则reload无效。

Worker 进程平滑重启不是“立刻重载代码”,而是主进程逐个替换旧 Worker,新进程必须重新执行 onWorkerStart 回调才能加载新代码——否则 reload 无效。
为什么 kill -USR1 后代码没更新?
常见错误现象:改了 Person.php,发了 kill -USR1 $pid,但新请求仍输出旧内容。
- 根本原因:被修改的文件没在
onWorkerStart中require_once或include,而是在 Server 实例化前就加载进内存了(比如直接require 'Person.php'在$serv = new swoole_server()上方) - 只有
onWorkerStart回调里动态加载的 PHP 文件,才会在每次 Worker 重启时重新解析 - 如果用了 OPcache,即使 reload 成功,也可能因缓存未失效而继续执行旧字节码;需配置
opcache.revalidate_freq=0或手动opcache_invalidate()
SWOOLE_PROCESS 和 SWOOLE_BASE 模式下 reload 行为差异
两种模式对连接和重启的支持完全不同,选错会导致连接中断或信号无响应。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
SWOOLE_PROCESS(默认):连接由 master 进程管理,kill -USR1只重启 worker,客户端长连接不受影响 -
SWOOLE_BASE:每个 worker 独立维护连接,不支持reload,发SIGUSR1会被忽略;强行调用$server->reload()会报错或静默失败 - 可通过
$server->mode或启动日志确认当前模式,切勿在 base 模式下依赖平滑重启
max_request 和 reload 的协作关系
max_request 是自动触发的“被动 reload”,和手动 SIGUSR1 是同一套进程替换机制,但触发条件不同。
-
max_request => 1000:worker 处理完第 1000 个请求后,自动标记退出 → 主进程拉起新 worker → 新 worker 执行onWorkerStart - 两者都依赖
onWorkerStart初始化逻辑,所以数据库连接、协程池等资源必须放在这里,不能放在全局作用域 - 若设
max_request=0(永不重启),又没配监控+自动 restart 工具(如 supervisor),worker 内存泄漏会持续累积,最终 OOM
如何验证 reload 确实生效?
别只看进程列表,要确认新 worker 是否真正加载了新代码。
- 在
onWorkerStart中打印getmypid()和当前时间戳,reload 后观察日志是否出现新 PID 和新时间 - 加一行
file_get_contents(__FILE__)或md5_file('Person.php')输出校验和,对比 reload 前后是否变化 - 注意:
ps aux | grep swoole显示的 PID 是 master 进程,真正要盯的是 worker 进程 ID(可通过swoole_server::stats()或日志中的worker_id关联)
最易被忽略的一点:reload 不重载 $serv->set() 配置项,比如改了 worker_num 或 max_conn,必须停服重启。业务代码热更和配置冷更,得分开管理。

















