2026-09-12-僵死半开连接治理与卡死现场取证.md

僵死/半开连接(ESTAB 但零吞吐)治理与卡死现场取证


一、先纠正因果:连接是受害者,不是元凶

一个空闲的已建立连接本身不消耗 CPU:没有数据可读、没有事件可派发,epoll 不会持续唤醒它。所以「7 条 ESTAB 连接 + CPU 94%」这个组合里,CPU 94% 只可能来自别处——事件循环当时正被独占/空转,于是:

那 7 条连接是受害者。上一轮已定位并修复的最可能元凶正是同步合并(readFileSync(64MB) + writeSync 逐块合并数 GB 文件):它同时解释了三件事——CPU 打满、事件循环停摆(连接全部僵住)、持续时间与合并体积成正比。修复后实测:3 个文件并发合并期间 /healthz 最大延迟 3ms。

结论:不要把「连接多/连接挂着」当成卡死的原因去治;要治的是「谁占住了事件循环」。

二、但你指出的缺陷真实存在,已补齐

排查确认服务端此前没有任何读空闲判定:

因此客户端掉线/关页/WiFi 闪断/网卡切换后,TCP 不会立刻释放,服务端就把这些「ESTAB 但零吞吐」的连接永久挂着,并残留写了一半的 .part。

三层兜底(已实现)

层机制参数
1连接级 TCP keepalive + setNoDelaysetKeepAlive(true, 30000)
2每 15s 巡检,销毁「上传中且超过阈值无数据」的连接DL_STALE_UPLOAD_MS(默认 120000ms)
3请求 error/close 时清理未完成的 .part(避免坏块污染续传会话)—

关键设计:只杀「上传中」的连接(socket 标记 kind='upload'),任何新请求开始即重置为 idle,因此长时间下载、WMV 转码、Office 预览等不会被误杀。

三、可观测性:下次卡死能直接定位

四、验证结果

1. 僵死连接自动判死(本次新增,精确复现你的场景)

用一个客户端发出 /api/upload/chunk 请求头 + 256KB body 后停住不发(不发 FIN、不再发数据,制造「ESTAB 零吞吐」):

起始:sockets=2 uploadSockets=1 staleUploads=0 半成品.part存在=true
t+110s  … uploadSockets=1 staleUploads=0 半成品.part存在=true
t+120s  … uploadSockets=1 staleUploads=1 半成品.part存在=true   ← 超过 120s 阈值
t+122s  客户端侧:连接已断开(ECONNRESET)                      ← 服务端主动判死
t+130s  sockets=1 uploadSockets=0 staleUploads=0 半成品.part存在=false  ← 垃圾已清理

服务端日志证据:

[warn] 清理僵死上传连接 127.0.0.1:53990(122s 无数据)→ 断开并丢弃未完成分块

→ 服务端现在会自己判死并清理,不再需要人工重启。

2. 回归测试

五、关于 192.168.31.110

它是在线的上传客户端(ping 1ms,MAC 00:e0:70:b9:41:97)。注意:该主机同时出现在本机的有线 enp3s0f1 与无线 wlp4s0 两个接口上 —— 这条线索很重要:

笔记本在有线/无线之间切换(或 WiFi 漫游到另一个 AP)时,旧接口上的 TCP 连接在服务端不会收到 FIN,会以 ESTAB 状态残留且零吞吐 —— 与「7 条挂着的连接」完全吻合。这类连接服务端必须自己能判死,本次的三层兜底正是针对这种场景。

可选的加固(当前未改,需要再快可自行启用):内核级更快回收

sudo sysctl -w net.ipv4.tcp_keepalive_time=120 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=3

(约 2.5 分钟由内核判定对端消失;应用层已有 30s keepalive + 120s 空闲判死,通常够用。)

六、参数与运维

可调参数(/etc/systemd/system/dl-server.service 的 Environment=):

curl -s --noproxy '*' http://127.0.0.1:8899/healthz   # 连接数/上传连接/合并队列/内存
tail -f ~/Downloads/dl-server.log                      # 关注 [warn] 事件循环阻塞 / 清理僵死上传连接
systemctl status dl-server dl-healthcheck.timer

七、相关文件

下载此文件