长连接为什么需要心跳?心跳、超时和重连如何设计?
简化版
长连接需要心跳来发现连接假死、NAT 映射失效、对端异常退出等问题。设计时要明确心跳间隔、超时时间、失败次数、重连退避和业务恢复策略。心跳不能太频繁,否则浪费资源;也不能太慢,否则故障发现延迟大。
详细版
TCP 连接在某些异常情况下不会立刻断开,例如对端断电、移动网络切换、防火墙丢弃空闲连接。应用如果不发送数据,可能长时间不知道连接已失效。
常见方案是客户端或服务端定时发送 ping,另一端回复 pong。比如每 30 秒发送一次心跳,连续 3 次未收到响应就认为连接不可用并重连。重连要使用指数退避和随机抖动,避免大量客户端同时重连打垮服务。
完整版教学
一、为什么 TCP 连接会假死
TCP 连接不是对端进程活着的直接证明。对端机器断电、网络中断、NAT 表项过期、防火墙丢弃空闲连接时,本端可能没有立即收到 FIN 或 RST。
client ---- NAT/firewall ---- server
idle too long -> NAT mapping removed
client still thinks connected
如果没有心跳,应用可能一直把这条连接当作可用,直到下一次真正写数据才发现异常。
二、TCP keepalive 和应用心跳
TCP keepalive 是内核级探测,应用心跳是业务协议里的 ping/pong。前者省事但默认周期长,后者可控且能携带业务状态。
| 机制 | 优点 | 缺点 |
|---|---|---|
| TCP keepalive | 内核处理,透明 | 默认慢,语义弱 |
| 应用心跳 | 间隔可控,可携带状态 | 需要协议支持 |
长连接系统通常两者结合:内核 keepalive 兜底,应用心跳负责及时检测和业务保活。
三、心跳间隔怎么选
心跳间隔要在资源消耗和故障发现速度之间折中。假设 100 万连接,每 30 秒一次心跳,每秒约 33333 次心跳请求;如果每 5 秒一次,每秒约 200000 次,压力差很多。
1,000,000 connections / 30s ≈ 33,333 heartbeats/s
1,000,000 connections / 5s = 200,000 heartbeats/s
所以不能拍脑袋设置很短。IM、推送、交易、监控系统对实时性的要求不同,心跳频率也不同。
四、超时和失败次数
一次心跳失败不一定代表连接坏了,可能是短暂抖动。常见做法是连续 N 次失败才判定断开。
heartbeat interval = 30s
miss threshold = 3
failure detection ≈ 90s
如果业务要求 10 秒内发现断线,就不能用 30 秒乘 3 的配置。参数要从业务 SLA 倒推。
五、重连退避和抖动
连接断开后不能所有客户端立刻疯狂重连。服务端发布、网络抖动或机房故障时,瞬间重连风暴会让系统雪上加霜。
retry delays: 1s, 2s, 4s, 8s, 16s
jitter: +/- random 20%
指数退避降低持续压力,随机抖动打散客户端重连时间。客户端还要有最大间隔和最大重试策略。
六、业务状态如何恢复
重连成功不代表业务自动恢复。长连接常有订阅、房间、会话、未确认消息、游标等状态。重连后要重新鉴权、重新订阅、补拉漏掉的数据。
connect -> auth -> resubscribe -> sync from last_seq
如果没有消息序号或 ack 机制,断线期间的数据可能丢失。心跳解决的是连接存活,不解决业务一致性。
七、服务端资源保护
服务端要限制空闲连接、心跳异常连接和重连频率。恶意客户端可能只建连接不发心跳,或者伪造大量心跳消耗 CPU。
| 风险 | 保护 |
|---|---|
| 空闲连接占资源 | idle timeout |
| 心跳风暴 | 限流/批处理 |
| 重连风暴 | 退避/熔断 |
| 连接泄漏 | 最大连接数 |
记忆钩子:心跳回答“连接还活着吗”,重连回答“断了怎么回来”,状态恢复回答“回来后业务怎么接上”。
监控上要分开看连接数、心跳延迟、心跳超时、重连次数和重连成功率。如果只看在线连接数,可能发现不了大量连接正在反复断开重连,用户体验已经很差。
heartbeat_timeout_rate
reconnect_attempts
reconnect_success_rate
八、常见误区与追问
- 误区:TCP 连接没断就说明对端还活着。 网络异常可能让连接假死,应用无感。
- 误区:心跳越频繁越好。 高频心跳会消耗带宽、CPU 和电量。
- 误区:重连成功就业务恢复了。 还要重新鉴权、订阅和补偿状态。
- 追问:为什么要随机抖动? 避免大量客户端在同一时间重连造成风暴。
- 追问:心跳由客户端还是服务端发? 都可以,取决于协议和连接管理模型。
- 追问:移动端心跳怎么考虑? 要兼顾耗电、后台限制、NAT 保活和消息及时性。
- 追问:如何判断连接假死? 超过心跳超时阈值或写失败后关闭并重连。
九、加强记忆
长连接心跳设计可以按四个词记:探测、判死、重连、恢复。心跳探测连接是否还可用,超时和失败次数决定何时判死,指数退避和抖动避免重连风暴,业务序号和重新订阅保证恢复后不丢状态。只讲 ping/pong 不够,必须把资源和业务恢复一起讲。