long connection closed before completion:长连接被提前关闭
long connection closed before completion严重程度 Medium长连接被对端按正常关闭流程结束,但早于业务完成的时间点。最可能是服务端或中转对连接存活时长设置了上限;第一步是统计多次断开时连接各自活了多久,看数值是否稳定。
结论
与粗暴的 RST 重置不同,这条错误里的连接是被礼貌地关闭的:对端走完了正常的关闭流程(TCP FIN 或 WebSocket close 帧),只是时机不对——你的任务还没做完。礼貌关闭意味着某一方是有意为之:它按自己的策略判断这个连接该结束了。排查的目标就是找出这个"有意"的一方和它的判断标准,而统计存活时长是最有效的手段。
适用环境
- 全部平台
- 流式接口、实时推送、隧道类长连接
一分钟快速判断
记录(或复现测量)最近几次断开时连接的存活时长:
- 时长高度一致(比如每次都在 300 秒左右)→ 存在硬性时长上限,通常在中转或服务端网关;
- 时长与"最后一次有数据"的间隔一致(比如总是静默 60 秒后被关)→ 空闲超时,转向心跳设置;
- 时长杂乱但断开时间点集中(比如总在整点、或某几分钟内大家一起断)→ 服务端批量回收(发布、重启、清理任务)。
这条错误代表什么
正常关闭的三种"有意":
- 最大存活时长(max lifetime):无论连接多活跃,到点就关。负载均衡器和一些中转服务用它强制连接轮转,避免单连接长期占用同一后端;
- 空闲超时(idle timeout):静默超过阈值即关。这是最普遍的一种,从 Nginx 的 60 秒默认值到各类网关的自定义配置都在这个家族;
- 主动回收:服务端发布新版本时优雅下线旧连接、或资源紧张时按最久优先清理。
三种策略都是合理的工程实践——问题只在于你的业务时长超过了它们的阈值。因此"修复"的形态也不同:心跳能对抗空闲超时,但对存活上限无效;重连机制则对三种都有效。
ConnProof 如何判断
connproof websocket wss://你的服务地址/path --hold 300000用五分钟的保持检测收集:连接实际存活的毫秒数、关闭方式(close 帧含 close code / FIN / RST)、以及 close code 的具体值——1000/1001 是常规关闭,1012(service restart)直接坐实服务端发布,1013(try again later)表明服务端过载。连续运行三次,三个存活时长的离散程度就是"硬上限 vs 随机回收"的分界证据。
最常见原因
- 中转/网关的空闲超时:默认值偏短(60~90 秒常见)而业务静默间隔更长;
- 最大存活时长策略:固定数值的规律性断开;
- 服务端发布或重启:断开集中在时间点,close code 常见 1001/1012;
- 客户端心跳失配:心跳间隔大于链路最短空闲超时,等于没有心跳。
Windows / macOS / Linux 排查步骤
- 三次
--hold 300000检测,记录存活时长与 close code; - 空闲超时画像:缩短应用心跳间隔到测得阈值的一半以下,复测确认存活时长突破原阈值;
- 硬上限画像:心跳无效,与服务方确认上限值,把业务改造为"上限内分段 + 自动重连续传";
- 服务维护者:检查自家反向代理的
proxy_read_timeout/proxy_send_timeout(Nginx)或对应网关参数,以及负载均衡器的连接时长配置——把它们对齐到业务最长静默期之上。
手机端排查步骤
- 手机后台连接被系统挂起后,服务端等不到心跳会按空闲超时正常关闭——这在手机上是常态而非故障,正确的适配是应用回前台后快速重连;
- 排查时保持应用在前台、屏幕常亮,先排除系统休眠因素再谈链路;
- 蜂窝与 Wi-Fi 的空闲阈值不同,分开统计。
如何区分本地问题和节点问题
| 证据 | 更可能是 |
|---|---|
| 存活时长固定 | 中转/服务端的时长策略 |
| 静默间隔固定后断开 | 空闲超时(心跳可解) |
| close code 1012/1001 且时间点集中 | 服务端发布重启 |
| 仅手机端频繁、桌面正常 | 移动系统后台策略(本地) |
| 换节点后阈值改变 | 该节点的中转配置 |
与重连机制和平共处
如果测量证实断开来自服务端的正常策略(存活上限、发布回收),最经济的应对不是消灭断开,而是让断开变得无感:确认客户端开启了自动重连,并检查两个参数——重连退避(首次重连应在一两秒内发起,之后指数退避,避免服务端刚发布完就被重连风暴打垮)和会话恢复(支持断点续传或会话续期的协议,重连后能接着上次进度走)。判断标准很实用:如果断开只在日志里可见、业务层面无感知,这个问题就已经"解决"了——不必追求一条永不断开的连接,那在公网上本来就不存在。
仍未解决时收集什么信息
- ConnProof 错误码(LONG-002)与脱敏报告;
- 三次测量的存活时长与 close code 列表;
- 心跳间隔调整前后的对照结果;
- 客户端名称和版本、操作系统版本。
禁止提交:完整订阅链接、密码、验证码、私钥、Token。
重新运行检测
connproof websocket wss://你的服务地址/path --hold 300000 --format markdown --output ws-report.md修复后连接应保持到目标时长并以你主动关闭结束。
相关文档
更新记录
- 2026-07-28:规则 v1 发布,确立存活时长统计三分法与 close code 判读。