Workerman reload 本质是子进程替换而非连接迁移,已建立的长连接仍由老进程服务直至自然关闭,新进程仅处理新连接;GatewayWorker 才是专为长连接不中断设计的分层方案。

Workerman reload 本质是子进程替换,不是连接迁移
Workerman 的 php start.php reload 不会维持旧连接在新进程中继续运行,它只保证「老进程不主动断开已有连接」。每个 Worker 子进程独立持有自己的 TCP 连接 fd,reload 时主进程通知老进程:处理完当前 onMessage、onClose 后退出;新进程启动后从零开始 accept 新连接。所以——已建立的长连接仍由老进程服务,直到它自然关闭或超时;但老进程不会把连接“移交”给新进程。这是设计使然,不是 bug。
GatewayWorker 才是专为长连接不中断设计的方案
如果你的应用依赖 WebSocket 或 TCP 长连接(比如 IM、实时看板),直接用纯 Workerman reload 必然伴随连接断开。官方给出的标准解法是分层:用 GatewayWorker 框架拆分为两层:
- Gateway 进程:只管维持客户端连接、转发数据,
$gateway->reloadable = false(默认不 reload) - BusinessWorker 进程:只管业务逻辑,
php start.php reload时仅重启它,Gateway 连接毫发无损
没上 GatewayWorker 却期望 reload 不断连,等于让 HTTP 服务器去扛 WebSocket 场景——能力边界错了。
reload 后连接看似“断开”的三个常见误判点
不是所有“断开”都来自 reload 机制本身,容易混淆的典型现象:
- 客户端未实现重连逻辑,老连接 close 后没自动 reconnect,看起来像“全断了”
- reload 前后
onConnect或onMessage里写了exit、die或未捕获的致命错误,导致老进程提前崩溃,连接被强制 reset - 用了
static $redis或全局单例,在 reload 后新进程读到的是旧进程残留的失效句柄,后续操作失败触发客户端主动断连
真正影响连接存续的关键配置项
即使走 GatewayWorker,以下配置写错也会让连接在 reload 期间异常中断:
-
$gateway->ping_interval = 0:禁用心跳,NAT/防火墙超时后静默断连 -
$gateway->ping_not_response_limit = 0:客户端不回 ping 也不踢人,积压无效连接拖垮资源 - Linux 内核参数
net.ipv4.tcp_fin_timeout过小:老进程退出后 FIN 包被快速回收,客户端收不到完整四次挥手
reload 是否断连,不取决于你敲了什么命令,而取决于连接生命周期是否和 Worker 进程生命周期强绑定——这点一旦模糊,后面所有优化都是在补漏洞。

















