发布于2026-07-15 阅读(0)
扫一扫,手机访问
平滑重启这事儿,听起来简单,但实际操作中不少人栽了跟头。它可不是主进程发个信号就完事了,而是需要逐一向worker进程发出通知,等它们处理完当前请求再优雅退出,然后新worker加载更新后的代码接替上岗。这里有个关键前提:你的业务代码必须在onWorkerStart回调里加载,否则改了也是白改,信号发过去根本没反应。
平滑重启不是“发个信号就完事”,而是主进程逐个通知 worker 处理完当前请求再退出,新 worker 加载新代码接替——前提是你的业务代码必须在 onWorkerStart 之后加载,否则改了也白改。
这个问题问得最多。常见场景是:改了代码,发个kill -USR1 $pid,结果日志没刷新,onWorkerStart没重跑,旧逻辑还在那里坚挺地执行。问题出在哪?
require 或 include 了,而 Swoole 的 reload 机制不会重新加载这些文件。onWorkerStart 回调里加载或初始化,这样每次 worker 重启时才会重新执行。onWorkerStart 中加一句 echo "worker {$workerId} start at " . date('Y-m-d H:i:s') . "\n";,发信号后看输出时间戳是否更新,一目了然。opcache.enable:如果开启了,需要配合 opcache_invalidate() 或者干脆禁用 opcache,否则 PHP 缓存的字节码不会跟着文件变动而更新。这两个参数直接影响平滑程度和资源回收节奏,但可不是设得越大越稳。有不少人把 max_wait_time 设成 300 秒,结果旧进程占着端口不放,新 worker 启动不了,整个服务反而卡住了。
reload_async => true 表示主进程不阻塞,异步触发 worker 退出;设为 false 时,主进程会等待每个 worker 自行退出,容易造成卡死。max_wait_time 是 worker 收到退出信号后最多等待多久(秒),超时则强制 kill。建议设为略大于你最长请求耗时,比如 30 秒,但别超过 60 秒,否则旧进程赖着不走。onWorkerStop 中显式调用 close(),否则连接残留会导致新 worker 初始化失败。不能只看进程 PID 变了就万事大吉,得实际验证服务连续性。这里有几个实用方法:
curl -v http://127.0.0.1:9501/test 配合一个长 sleep 请求(比如接口里写 sleep(15)),在请求进行中发 kill -USR1,观察是否返回成功且没有 connection reset。ps aux | grep php:旧 worker 进程状态应变为 Z(zombie)或消失,新 worker PID 全部更新,说明没有残留。onWorkerStart 和 onWorkerStop 日志,确认两者时间差合理。比如 stop 在 start 之前 2 秒内,说明没有“空窗期”,服务是连续的。onReceive 或 onRequest 中写全局变量或静态属性,因为 worker 重启后状态不继承,会导致数据错乱。真正容易被忽略的是:Swoole 的 reload 只能更新 worker 进程的用户代码,Master 进程、Manager 进程、Task 进程的代码和配置都无法热更新。一旦涉及 server->set() 参数变更(如 worker_num、task_worker_num)、PHP 版本升级、扩展变动,就必须停机重启主进程——这时候就得靠蓝绿部署或滚动发布兜底了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8