凌晨的订单推送突然变慢:反向代理按空闲超时切断连接,客户端恢复网络后集中重连,数千请求压垮新实例。滚动发布中,旧实例先退出、新实例未就绪,重复注册和消息重投继续放大故障。难点不在断线,而在断线后的探测、错峰与幂等边界。
如果你正在选机器,或者想先把线路和配置跑通再谈长期方案,可以先看看这几家的线路说明和技术参数:vpckr(韩国高端低延迟基础设施),先看清带宽线路、流量策略和退款条款,再决定要不要迁。
弱网会放大问题。心跳只能说明链路暂时可用,不能证明业务处理成功;退避只能分散重连,不能消除重复投递。代理超时、实例切换与消息确认必须协同设计。
若服务端长期没有业务帧,代理仍会按空闲阈值清理连接。应用层每20秒发送ping,连续3个周期收不到pong或校验失败,即标记连接不可用。但心跳不代表可靠:代理会清理半开连接,浏览器也可能切换网络。需监听close、error和网络状态,结合最近pong时间、失败次数与队列水位判断,避免固定阈值误判。

心跳间隔应小于代理最短空闲阈值,并留一次重试余量;过密挤占带宽,过疏则来不及发现断线。pong携带会话标识,客户端据此丢弃旧连接的迟到响应。
重连不能立即循环。指数退避可从1秒、2秒、4秒、8秒递增,30秒封顶,再加0至500毫秒随机抖动,避免同秒冲击集群。401或403先刷新凭证,503或实例未就绪才继续退避。服务端按优雅下线流程拒绝新连接,发送closing原因,等待在途消息完成,再关闭并引导切换实例。

连上后仍可能收到重复事件。重连时携带最后确认序号,每条事件带按会话递增的消息序列号,客户端只处理大于已确认序号的连续消息;出现缺口就暂停并请求补发,旧序号丢弃。服务端生成稳定业务键,消费端按业务键和状态执行幂等消费机制:成功键返回原结果,执行中拒绝并行处理,失败后才重试。
验证时不要只看连接成功率。应模拟pong延迟、重复帧、滚动发布和超时重连,观察心跳误判率、重连峰值、序号缺口与重复执行数。若重连整齐扎堆,说明缺少抖动;若序号连续却重复扣款,说明幂等键失效;若下线后仍频繁注册,应检查优雅下线是否生效。
连接建立不等于消息可靠到达。服务端应维护递增的消息序列号,客户端保存最后处理的序号;重连时携带该序号,服务端只补发后续消息。无法续传就返回完整快照及当前序号。客户端应在业务处理成功后确认,失败消息继续保留,避免“先确认、后处理”造成缺口。
幂等消费机制要同时使用业务事件ID与序列号:前者拦截重复,后者发现遗漏。消费记录应与业务写入处于同一事务,并为事件ID设置唯一键;处理后尚未确认便崩溃时,重放消息也不能重复扣款或通知。
WebSocket心跳检测应覆盖链路空闲、发送失败和业务阻塞,不能只看 readyState。超时后关闭旧连接并进入统一重连状态,同时清理旧定时器,避免一次断线触发多次重连;页面恢复可见或网络恢复时也应主动探测。
常见坑是固定间隔重连造成惊群、服务重启后序号错误重置,以及旧连接的迟到消息覆盖新连接。重连应使用带随机抖动的重连退避算法,从1秒指数增长并封顶30秒;序号规则变化时切换会话世代或强制拉取快照。断线原因、重试次数、补发量和消费延迟都要记录,否则“在线却收不到”无法定位。

优雅下线流程应先摘除负载均衡并停止接收新连接,再停止生产消息;随后发送最终序号,等待在途消息落库、客户端确认和短暂补发窗口结束,最后发送正常关闭帧。超时才强制断开,但必须保留可重放日志,避免发布时产生数据缺口。
上线前至少完成一次“断网恢复”和一次“发布中断”的端到端演练,确认客户端能自动续传、补偿缺口且不重复执行。只有恢复、幂等、观测三条路径都可验证,自动重连才真正可靠。