首页/网络/协议速查/半开连接与死连接检测
TCP 与 UDP54 条

半开连接与死连接检测

一端重启/断电后,另一端内核仍保留 ESTABLISHED(半开连接),不主动探测就永远不知道对端已消失。

协议速查网络更新于 2026-10-13

对端消失但本端不知道

半开连接指一方已经重启、断电或进程崩溃,另一方内核里却仍保留着 ESTABLISHED 状态。TCP 本身没有「对端还活着」的周期性确认,只有真正发送数据并等待确认时才会发现异常。因此长连接场景必须依靠 TCP keepalive 或应用层心跳来主动探测,否则连接池里会慢慢堆积一批永远不可用的连接。

基本信息

适用平台所有 TCP 实现;Linux 参数位于 net.ipv4.tcp_keepalive_*
探测手段TCP keepalive(内核)或应用层心跳(可携带业务状态)
Linux 默认约 2 小时空闲后才开始探测,生产环境需要调小
相关参数tcp_keepalive_time 空闲时长、tcp_keepalive_intvl 探测间隔、tcp_keepalive_probes 探测次数

检测方式对比

方式触发时机优缺点
TCP keepalive内核按空闲时长自动探测无需改代码;探测发空 ACK,不携带业务信息
应用层心跳应用按业务周期发送能携带业务状态、可自定超时;需改代码
负载均衡空闲超时中间设备按自身超时切断配置不当会表现为偶发重置
写超时与重试发送数据时发现异常被动发现,最慢但最可靠

查看与调整 keepalive

查看与调整 keepalive
ss -tio | grep -i timer                   # 观察连接当前的定时器状态
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes
# 生产常用:300 秒空闲后开始探测,间隔 30 秒,连续 3 次无应答即断开
sysctl -w net.ipv4.tcp_keepalive_time=300 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=3
# 单进程级别可由应用通过 setsockopt(SO_KEEPALIVE) 单独开启

典型使用场景

  • 长连接网关与推送服务:及时清理死连接,避免写失败时才暴露问题
  • 连接池维护:定期探测并剔除不可用连接,降低首次请求失败率
  • 排查「偶发连接被重置」:确认是中间设备空闲超时还是对端真的挂了
  • 数据库连接池与中间件客户端的存活检测策略评估
云负载均衡通常有自己的空闲超时(常见 60 秒到 900 秒):后端 keepalive 必须比它更短,否则会出现「连接看起来在、但一写就失败」的偶发重置。
移动网络与 NAT 设备会主动清理长时间空闲的映射:跨 NAT 的长连接建议使用应用层心跳而不是内核 keepalive,因为空 ACK 不携带业务语义,也无法确认对端应用是否健康。

易错点

  • keepalive 探测发的是空 ACK,不携带数据:某些 NAT 仍会过期映射,跨 NAT 长连接要靠应用心跳
  • 默认 2 小时的探测间隔太长:对端早已崩溃的连接会长期占用连接池名额,首个请求才暴露失败
  • 只调内核不调应用:应用自己也有读写超时,两者不匹配时仍会先触发应用层错误
  • 把中间设备的空闲超时当成对端故障:频繁重置往往源于负载均衡超时小于后端 keepalive 周期

数据来源与参考

  • RFC 9293 §3.8.4(keepalive)
  • man 7 tcp

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌