heartbeat_check_interval 是 swoole websocket server 的心跳检测间隔(秒),仅在 enable_heartbeat_check=true 时生效,需配合 heartbeat_idle_time 使用,且仅适用于 swoole_websocket_server。

heartbeat_check_interval 是什么,设了但没生效?
heartbeat_check_interval 是 Swoole Server 的一个配置项,用于控制心跳检测的间隔(单位:秒),但它**只对 WebSocket 连接生效**,且**仅在启用了 enable_heartbeat_check 时才起作用**。很多人设了这个值却没看到心跳包被发送或连接被断开,根本原因是:它不作用于 TCP/HTTP Server,也不影响客户端主动 ping —— 它是服务端单向、周期性检查客户端是否还“活着”的机制。
- 必须同时设置
enable_heartbeat_check => true,否则heartbeat_check_interval被忽略 - 该配置对
swoole_http_server和swoole_server(TCP)完全无效,哪怕你写进配置里也不会报错,只是静默丢弃 - 实际检测逻辑是:服务端每
heartbeat_check_interval秒扫描一次所有 WebSocket 连接,若某连接在heartbeat_idle_time内未收到任何帧(包括 ping/ping/pong/text/binary),则触发onClose
正确设置 heartbeat_check_interval 的最小必要配置
只配 heartbeat_check_interval 不够,必须搭配 heartbeat_idle_time 才能形成完整心跳策略。这两个值的关系是:heartbeat_idle_time 必须 ≥ heartbeat_check_interval,否则 Swoole 会自动将其调整为等于 heartbeat_check_interval(v4.8.13+ 版本行为)。
-
heartbeat_check_interval => 30:服务端每 30 秒检查一次连接活跃度 -
heartbeat_idle_time => 60:客户端只要 60 秒内发过任意 WebSocket 帧,就视为存活;超时则关闭连接 - 典型组合是
check=10+idle=30,适合对响应延迟敏感的实时场景 - 注意:Swoole 不会主动发 ping 帧,它只被动等待客户端发帧;你要实现双向心跳,得自己在
onMessage里处理ping并回pong
常见错误:为什么连接没被自动断开?
最常遇到的现象是:客户端断网或 kill 进程后,服务端很久才触发 onClose,甚至不触发。这通常不是 heartbeat_check_interval 没生效,而是底层连接状态没及时暴露给 Swoole。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- Linux 默认 TCP keepalive 时间是 2 小时,内核层不会快速通知进程对端已失联;Swoole 的心跳检查依赖的是应用层帧时间戳,不是 TCP 状态
- 如果客户端只是「挂起」(如手机锁屏、浏览器标签页休眠),它可能停止发帧,但 TCP 连接仍保持 ESTABLISHED,此时
heartbeat_check_interval才真正起作用 - 务必确认你用的是
swoole_websocket_server,而不是swoole_http_server—— 后者即使升级到 v5.x,也不支持该配置 - 检查日志:开启
log_level => SWOOLE_LOG_DEBUG,搜索heartbeat关键字,能看到每次检查的连接数和超时数
PHP 代码中怎么写才可靠?
直接在 Server 构造时传入配置即可,不需要运行时调用方法。示例中省略了回调注册,只聚焦配置本身:
$server = new swoole_websocket_server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$server->set([
'enable_heartbeat_check' => true,
'heartbeat_check_interval' => 25,
'heartbeat_idle_time' => 75,
'log_level' => SWOOLE_LOG_DEBUG,
]);
注意:heartbeat_idle_time 设为 75 表示允许最长 75 秒无帧,但检查频率是 25 秒一次,所以最坏情况下连接会在第 75 秒末被关闭,而非第 100 秒。这个延迟边界容易被误判为配置失效。
真正的复杂点在于:它不解决网络闪断、NAT 超时、代理中断这类问题,只管应用层帧时间。如果你需要更激进的连接清理,得结合 tcp_keepidle/tcp_keepintvl 系统参数,或在业务层加定时 ping。










