Workerman 5.2.3平滑重启本质仍是php start.php reload触发SIGUSR1信号,老进程处理完当前请求并拒绝新连接后退出,新进程加载最新代码立即接单,客户端无感知;但仅对onMessage等回调中动态require的逻辑生效,静态定义、OPcache缓存及构造阶段初始化内容不会刷新。

Workerman 5.2.3 的平滑重启本质没变,核心仍是 php start.php reload 触发主进程向子进程发送 SIGUSR1 信号,实现老进程处理完当前请求、拒绝新连接、自然退出,新进程加载最新代码立即接单——整个过程客户端无感知,连接不中断。
但要真正“不丢连接”,光执行命令远远不够,关键在代码写法和运行环境是否配合这个机制。下面分几块说清楚。
reload 只对运行时动态加载的逻辑生效
Workerman 不会重载启动阶段就固化的内容。比如:
- ✅ 有效:
onMessage回调里require 'logic_v2.php',reload 后会重新读取文件 - ❌ 无效:
$worker->name = 'old_handler'写在new Worker()后;define('VERSION', '1.0');或class_exists('OrderService')提前加载的类
这些 reload 不会刷新,必须restart(即php start.php restart),否则新逻辑根本不会执行。
OPcache 是线上 reload 失效最常见原因
PHP CLI 模式下 opcache.enable_cli=1 开启时,旧字节码会被缓存,reload 后实际还在跑旧代码。解决方法有两个:
- 推荐:在
onWorkerStart中加opcache_reset(),确保每次子进程启动都清空缓存 - 或直接关闭 CLI 的 OPcache:在
php.ini或启动命令中设opcache.enable_cli=0
避免静态状态导致逻辑错乱
静态变量、全局数组、单例对象在 reload 后仍保留在原进程内存中,不会重建:
-
static $counter = 0;→ reload 后还是上次的值,不是 0 -
MyCache::getInstance()返回的仍是旧实例
这类状态应改用外部存储(Redis)、或确保在onWorkerStart中显式重置/重建。
验证 reload 是否真生效,别只信终端提示
执行 php start.php reload 后:
- 查
php start.php status,对比前后 Worker 进程 PID 是否变化 - 看日志是否有新
worker#0 started记录 - 在
onMessage里临时加echo "v2.1\n";并用telnet或 WebSocket 客户端触发,确认输出更新
基本上就这些。只要代码没把业务逻辑写死在初始化阶段、OPcache 不锁住旧代码、也没有残留静态状态,5.2.3 的 reload 就能稳稳做到连接不断、逻辑更新。

















