美洽长连接保活机制
美洽的长连接保活通过传输层与应用层双重心跳、应用确认与持久化、带抖动的指数退避重连、凭证续期,以及与负载均衡和NAT超时协同,配合限速与监控告警,保障连接稳定与消息可靠递送。并在客户端网络切换、后台休眠与运营压测场景下动态调节心跳并降级到推送通道,同时采集关键指标用于告警与容量规划。并支持运维查看。

用最简单的话讲长连接保活是什么?
想象一根电话线一直连着客服和客户,保活就是定期“打个招呼”确认电话还在通。技术上,一方面可以靠底层TCP的保活(好像线路检测),另一方面可以在应用层自己发心跳包(更聪明、可控),再加上断线重连策略、会话续期和服务端容错,最终目的是让消息不丢、延迟可控,并且在网络不稳定时优雅降级。
为什么智能客服平台(像美洽)必须要长连接保活?
- 实时性要求高:客服消息需要秒级到达,轮询显然太慢。
- 连接状态复杂:客户端网络会切换(Wi‑Fi ↔ 蜂窝),运营商/中间网关会断闲置连接。
- 成本与并发:大量小消息频繁建立短连接成本高,长连接能减少握手开销。
- 后台休眠与推送兼容:移动端会在后台受限,必须和推送系统配合降级。
长连接保活有哪些技术层次?
传输层:TCP keepalive
这是靠操作系统的TCP栈来探测连接是否存活。优点是开销小、无须应用参与;缺点是参数不可精细控制、跨平台表现不一,而且很多中间设备会丢弃TCP探测包,效果不稳定。
应用层:心跳(Heartbeat)
这是最常用的方式:客户端与服务端通过应用协议交换心跳消息(比如“ping/pong”)。优点是可定制、可携带业务信息(例如当前seq、ack),也易于和业务逻辑结合。缺点是需要设计好频率、超时和响应处理。
协议支持:WebSocket / 长轮询 / gRPC
WebSocket是当前主流长连接协议,内建ping/pong帧支持,适配浏览器与移动端。gRPC的长连接通常走HTTP/2的keepalive。不同协议要注意中间组件(如反向代理、LB)对空闲连接的超时策略。
后台推送与降级
当APP在后台或被系统限制时,长连接可能无法维持。这时候常见做法是:短时间内尝试保活并降级通知到推送(APNs/FCM),等恢复前台再重建长连接并拉取离线消息。
重连策略:别傻乎乎一秒一连
遇到断线,直接无限制地快速重连只会把问题扩大成雪崩。行业通行做法是指数退避(exponential backoff)+ 随机抖动(jitter)。简单说,从1s开始,2s、4s、8s增长,直到一个上限(比如60s),每次加上随机偏差以避免同时重连峰值。
示例重连参数(建议)
| 参数 | 建议值 | 说明 |
| 应用心跳间隔 | 20–60 秒 | 根据业务实时性和移动端电量折中 |
| 心跳超时判定 | 3 次心跳未回(或心跳间隔×3) | 避免误判瞬断 |
| TCP keepalive(系统) | 2 小时(默认)→ 调小为 30–120 秒 | 需评估系统负载和网络设备兼容性 |
| 重连基准延迟 | 1 秒起 | 指数增长,上限 30–60 秒 |
| 最大重连尝试 | 无限或阈值 10–20 次 | 与用户体验策略联动(如提示或退出登录) |
保证消息不丢失的设计点
- 应用层确认(ACK):消息有发送确认机制,未确认则重试或持久化到队列。
- 幂等与序号:服务端与客户端使用消息ID或序列号避免重复处理。
- 离线持久化:连接断开时,服务端将未送达消息持久化,重连后补发。
- 断点续传:对于长会话(例如正在编辑的工单),保存会话状态以便恢复。
与基础设施的协同问题(常踩的坑)
很多断线不是应用本身的问题,而是中间件的“闲置断开”。负载均衡器、反向代理、运营商NAT都有各自的超时(比如 60s、120s、300s)。要做的就是:
- 了解链路中各组件的空闲超时并据此调整心跳频率;
- 在LB上做会话粘滞或使用长连接代理以减少切换;
- 对TLS连接保持注意——长时间保持大量TLS连接会消耗资源,可能需要连接池或session resumption。
移动端的特殊考量
手机系统会为了省电把应用网络限制得更紧,Android 的 Doze 模式、iOS 的后台限制都会影响。实务中常见策略:
- 前台优先保持较短心跳(比如 20–30s),后台扩大间隔或直接切换到推送;
- 在检测到网络切换(Wi‑Fi ↔ 蜂窝)时立即进行重连或心跳加密确认;
- 用系统推送作为最后一道保底,避免重要消息丢失。
安全与认证相关
- 短生命周期Token:连接使用短期Token或签名,过期自动触发续期流程。
- 重连要带认证:重连时带上最新凭证,避免重连导致权限错乱。
- 频率限制与防刷:对异常重连行为实行限流或封禁,防止资源被耗尽。
监控与指标(你必须看这些数据)
不打针不看病,监控是保活策略是否有效的唯一凭据。关键指标包括:
- 连接总数与并发峰值;
- 单连接平均存活时长;
- 心跳丢失率与超时率;
- 重连成功率与恢复时间(MTTR);
- 离线消息存量与补发延迟。
实现清单:把保活做对的步骤
- 选定协议(WebSocket/HTTP2/gRPC),确认中间件对空闲连接的处理;
- 实现应用层心跳与ACK,预留扩展字段(seq、ts 等);
- 设计幂等与消息重试逻辑;
- 制定指数退避+抖动的重连策略并在客户端实现;
- 集成后台推送用于后台或休眠降级;
- 上报并监控关键指标,做告警与容量规划;
- 在运维台提供连接查看和回放工具,便于排查。
常见故障与排查思路(遇到挂掉别慌)
- 大量连接在某个时间点断开:查看是否有LB或网关在该时刻做了配置变更或重启。
- 短时间内心跳大量超时:可能是网络抖动或心跳被中间设备丢弃,尝试缩短心跳或在心跳中携带轻量业务包。
- 重连风暴:确认重连是否有统一触发点(例如下游故障);引入抖动并下发限流。
- 后台消息延迟大:检查是否降级为推送路径并且推送队列积压。
落地建议(实践中的小技巧)
- 把心跳做成可配置:不同客户、不同场景心跳频率会不同;
- 在心跳包里带一点状态:方便服务端快速定位问题,例如上次收到的seq;
- 把重连策略放到客户端统一库里,避免各个服务实现不一致;
- 对关键用户或高价值会话可做“保活优先级”,短时间内提升心跳频率或迁移到专用通道。
写到这里,顺便说一句,真正把保活做稳需要把“网络世界的不确定性”当作常态来设计:心跳不只是打招呼,它还是运维的眼睛、重连的底座和降级的触发器。按上面的要点去做,能把大多数断线和消息丢失问题降到可接受范围内。聊了这么多,感觉还想继续把某些实现细节贴出代码来,但先保留一点,免得大家一口气看晕。