heartbeat_check_interval 是后台心跳检测线程的轮询间隔,决定多久全量扫描一次连接,而非实时检测;其值必须小于 heartbeat_idle_time(推荐 1/3~1/2),否则可能导致误杀或延迟高达二者之和。

heartbeat_check_interval 不是“检测频率”,而是“扫描周期”——它决定 Swoole 多久遍历一次全部连接,不等于每次都能精准发现超时连接。
heartbeat_check_interval 的真实作用
这个参数控制的是后台心跳检测线程的「轮询间隔」,不是实时监控。Swoole 不会为每个连接单独起定时器,而是在每个 heartbeat_check_interval 秒触发一次全量扫描,挨个检查每个连接的最后活跃时间是否超过 heartbeat_idle_time。
常见误解是设成 5 秒就能 5 秒内断掉死连接——实际最大延迟可达 heartbeat_check_interval + heartbeat_idle_time(比如 check=30、idle=60,最坏情况要等 90 秒才关)。
- 只设
heartbeat_idle_time不设heartbeat_check_interval:检测线程根本不会启动,心跳失效 -
heartbeat_check_interval≥heartbeat_idle_time:逻辑上矛盾,可能导致连接刚建立就被误杀 - 值过小(如 1~3 秒):高并发下每秒扫描数万 fd,CPU 毛刺明显,尤其在 10k+ 连接场景
和 heartbeat_idle_time 的配合关系
这两个参数必须成对出现,且存在强约束:heartbeat_check_interval 必须小于 heartbeat_idle_time,理想比例是 1/3~1/2。
例如业务流式响应间隙最长 45 秒(LLM 场景),heartbeat_idle_time 至少设为 60,对应 heartbeat_check_interval 推荐 20~30;若设成 5,则每 5 秒扫一遍 2w 连接,单次扫描耗时可能超 100ms,反而拖慢主循环。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- idle = 0:禁用心跳,所有连接靠 TCP 四次挥手或 RST 清理,弱网下大量僵尸连接堆积
- check = 0 或负数:配置被忽略,退化为无检测
- 未设置 check 但调用
$server->heartbeat():可手动触发单次扫描,适合做兜底或调试
不同业务场景下的典型取值
没有通用最优值,得看你的连接行为特征:
- IM 类(消息密集):
heartbeat_check_interval => 15,heartbeat_idle_time => 30 - LLM 流式长连接(响应间隙大):
heartbeat_check_interval => 60,heartbeat_idle_time => 300 - IoT 设备(低功耗、心跳包稀疏):
heartbeat_check_interval => 120,heartbeat_idle_time => 600
注意:Linux 内核 tcp_keepalive_time 默认 7200 秒,远大于 Swoole 层配置,所以不要指望靠系统 keepalive 来兜底——它压根赶不上应用层节奏。
容易被忽略的兼容性细节
Swoole v4.7+ 支持 per-port 心跳配置,但老版本(v4.6 及以下)全局唯一,改一个端口就全端口生效。升级前务必确认:
- 旧代码里写死的
set(['heartbeat_check_interval'=>...])在多端口模式下会覆盖其他端口配置 - v4.7 新增的
addlistener返回的$port对象支持独立set(),但必须在addlistener之后立即调用 - CLI 启动时若用
-d模式,heartbeat_check_interval日志不会输出,需查strace -e trace=epoll_wait确认线程是否真在跑
真正麻烦的不是配错数值,而是把 heartbeat_check_interval 当成毫秒级精度的探测开关——它本质是个粗粒度资源巡检机制,精细控制还得靠应用层 ping/pong 帧。










