凌晨值班时,客户端的 WebSocket 连接常在 3060 秒后集体重连:代理没有 5xx,曲线却在固定时刻出现尖峰。表面像网络抖动,实际要追应用、代理与客户端的时间线。
如果你正在选机器,或者想先把线路和配置跑通再谈长期方案,可以先看看这几家的线路说明和技术参数:sixtynet(全球云服务器),先看清带宽线路、流量策略和退款条款,再决定要不要迁。
一、断线背后是四套计时器
代理设有空闲、连接和读取超时,系统维护 TCP keepalive,应用层另有心跳。连接保活机制的尺度并不一致:代理超时边界若贴近心跳周期,就会在客户端看似活跃时切断上游;上游短时无响应,代理也会释放连接。TCP keepalive 不能替代业务心跳,也醒不了阻塞线程。
半开连接多见于 NAT 清理会话映射。对端已消失,本机却仍显示 ESTABLISHED;继续写入时,数据先入缓冲区,直到重传耗尽才报错,代理只看到无流量。若事件循环被同步调用、锁竞争或连接池耗尽拖住,心跳同样积压,存活但无响应的链路也会被判超时。

先核对三点:断开是否落在固定秒数;此前有无 FIN、RST 或重传;心跳响应是否贴近超时。越有规律,越应先查计时配置,而非换线路。
二、把断线放进同一条时间轴
不要只看客户端的“已断开”。给握手、心跳和重连分配同一 trace_id,记录代理状态、关闭时刻,以及应用事件循环延迟、线程池队列和下游耗时。两侧日志不齐,半开连接检测容易把路径丢包误判成服务器重启。

用三组受控实验定位:连接后保持业务静默,观察是否在代理空闲阈值处关闭;定时发送小心跳并要求即时响应,确认能否跨过空闲窗口;在预发环境暂停下游依赖或制造线程阻塞,对照心跳与代理日志。每组只改一个变量。
Linux 现场可用 ss 看套接字队列,用 tcpdump 对照 FIN、RST 与重传,应用侧查事件循环 lag 和线程转储。踩坑是只改一个数字:代理超时从 60 秒延到 600 秒,应用线程仍阻塞 120 秒,连接只是更晚断开,根因未消失。TCP keepalive 也不宜调得过密。
稳妥原则是:心跳加入少量抖动,代理空闲窗口保留余量,接收端设置响应期限;客户端采用带上限的重连退避策略,避免恢复时形成重连风暴。优雅滚动发布前记录心跳间隔、空闲超时和重试预算。需要固定抓包时,可用随身服务器旁路留存。
用超时边界约束长连接生命周期
长连接调优的核心,是让每一层明确“何时继续、何时断开、何时重连”。客户端、入口代理和上游服务各有空闲超时;只改某一层,连接仍可能在看似活跃时被中间节点回收。应先画出完整链路,再统一计算从请求结束到连接关闭的最短时间。
代理超时边界必须覆盖 TCP 空闲、TLS 握手、响应头等待、响应体传输和 keepalive 探测窗口。入口读取超时不能小于上游处理时长上界,心跳也要预留抖动余量;超时过长则会积累失效连接,占满文件描述符和后端连接池。多层代理串联时,应按最短边界设计。
半开连接检测说明连接保活机制不能只依赖 TCP,因为对端掉电或网络黑洞时,套接字可能仍显示 ESTABLISHED。应用层心跳应携带递增序号,并设置“收到下一序号”的截止时间;连续丢失达到阈值后,将连接标记为不可用,主动关闭并重建。探测频率过高会制造控制流量和日志风暴。
把重连、摘流与发布编排成闭环
发布时,优雅滚动发布不是停止接收新请求就结束。旧实例应先进入 draining:停止接收新流量,但允许存量请求和长连接继续工作;同时通知客户端或代理触发重连,并设置最长排空时间。直接杀死旧进程常表现为 reset,容易在发布瞬间引发集中重连。

重连退避策略宜采用指数退避加随机抖动,从数百毫秒起步,逐步扩大上限,并设置总等待时间和最大尝试次数。固定间隔会在实例恢复时形成惊群;只重试一次又可能把短暂故障放大。重连前应区分连接失败、认证失败和请求超时,后两类不应盲目重试。
常见坑包括:把业务心跳与代理健康检查混为一谈;只看平均延迟,不看 P99、重连率和半开连接数;调整超时后未同步连接池;滚动发布时新旧实例配置不一致。监控至少应包含活跃连接、空闲时长、心跳失败、重连次数、拒绝数、连接池等待时间及异常关闭原因,并按实例和版本切分。
可执行检查清单:①梳理客户端到上游的超时链,确认最短边界和重试总时长;②压测空闲、慢响应及网络抖动,验证半开连接能被及时识别;③核对 keepalive 周期、失败阈值与日志采样,避免探测风暴;④演练实例摘除、代理重启、发布及回滚,观察排空和重连抖动;⑤启用带抖动的指数退避、次数上限与熔断;⑥发布前核对新旧实例配置,再依据连接数、错误率、P99 延迟和重连率决定是否全量。


喜欢
顶
难过
囧
围观
无聊





