onclose在swoole中于tcp连接正常(fin)或异常(rst/超时)断开时触发,仅对已完成握手的连接生效;不触发场景包括客户端未发fin(如拔网线)、http/1.0无connection:close、websocket未发close帧、worker被kill-9等。

onClose 在 Swoole 中的触发时机
onClose 是 Swoole Server 的连接关闭回调,**仅在 TCP/UDP/Unix Socket 连接被正常或异常断开时触发,且仅对已成功完成握手(即已进入 onConnect 或 onReceive 流程)的连接生效**。它不会在握手失败、SSL 握手中断、或连接被防火墙静默丢弃时调用。
哪些情况 onClose 不会触发
这是最容易误判的地方:很多开发者以为“只要客户端断了,onClose 就一定执行”,但实际有多个常见漏点:
- 客户端未发送 FIN 包(如直接 kill 进程、拔网线、NAT 超时静默回收),此时连接处于半开状态,Swoole 默认不感知,
onClose不触发 - HTTP 模式下,客户端使用 HTTP/1.0 且未带
Connection: close,Swoole HTTP Server 不会在响应后主动关连接,后续空闲超时由keep_alive_timeout控制,此时断连走的是心跳/超时机制,不一定进onClose - WebSocket 子协议中,若客户端未发
close帧(如页面刷新、浏览器崩溃),服务端可能只收到 RST,部分版本 Swoole(尤其是4.8.0之前)对 RST 的处理不保证触发onClose - Worker 进程被
kill -9或发生致命错误退出时,已建立的连接不会逐个走onClose,而是随进程直接销毁
onClose 的参数与典型用途
回调函数签名是 function (Swoole\Server $server, int $fd, int $reactorId)。注意:$fd 是连接文件描述符,不是用户 ID;$reactorId 表示该连接由哪个 Reactor 线程处理,可用于调试分发逻辑。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
常见用途包括:
- 从
$server->connections或自维护的fd → user_id映射表中清理连接记录 - 向 Redis 发布“用户下线”事件(需确保操作是异步安全的,避免阻塞 Reactor)
- 记录连接生命周期日志(建议只记关键字段,如
$fd、$reactorId、耗时,避免 I/O) - 不要在
onClose中调用$server->close($fd)—— 此时连接已关闭,再调用会报Invalid argument
如何提高 onClose 的可靠性
依赖被动关闭不可靠,必须叠加主动探测机制:
- 启用
heartbeat_check_interval(TCP)或websocket.heartbeat_ping(WS),让 Swoole 定期发 ping 并自动踢掉无响应连接 - 对关键业务连接,在
onReceive中更新 last_active 时间戳,另起定时器扫描超时连接并手动close - 升级到 Swoole
5.0.3+或4.8.15+,这些版本修复了多处 RST / FIN 未触发onClose的 edge case - 若使用
open_tcp_nodelay = true,注意某些内核版本下 FIN 包延迟合并可能导致onClose延迟数百毫秒,压测时需关注
真正难处理的永远是“没消息=死了吗”,onClose 只是结果通知,不是死亡检测本身。










