Linux服务器FIN_WAIT2连接过多怎么办?四次挥手、对端不关闭与 tcp_fin_timeout 排查教程
本内容发表于:2026-09-01 15:36:11
浏览量
1050

Linux 服务器出现大量 FIN_WAIT2,说明本机已经主动发起连接关闭,对方也确认收到了本机的 FIN,但迟迟没有发送自己的 FIN。少量、短时间存在的 FIN_WAIT2 属于正常的 TCP 关闭过程;如果数量持续增长、流量回落后仍不消失,或者同时出现文件描述符、端口及内存压力,就需要查明连接属于哪个业务、对端为何没有完成关闭,以及套接字是否仍被应用程序持有。

FIN_WAIT2 表示什么?

本机主动关闭 TCP 连接后,先进入 FIN_WAIT1;收到对端对本机 FIN 的确认后,进入 FIN_WAIT2;等对端也发送 FIN,本机确认后才进入 TIME_WAIT。因此,FIN_WAIT2 的重点是等待对端完成关闭。

  • FIN_WAIT2:本机已关闭发送方向,正在等待对端关闭。

  • CLOSE_WAIT:本机已收到对端的 FIN,但本机应用还没有关闭套接字。

  • TIME_WAIT:双方关闭过程基本完成,本机暂时保留状态以处理迟到报文。

看到 FIN_WAIT2 时,不要立即认定是 Linux 内核故障。对端应用未关闭、代理超时不一致、长连接设计以及异常网络路径,都可能让连接停留在这个状态。

先确认连接是否持续累积

ss -ant state fin-wait-2 | wc -l
ss -s
watch -n 5 'ss -ant state fin-wait-2 | wc -l'

发布、滚动重启、代理切换或短时流量高峰都可能让 FIN_WAIT2 暂时增加。更值得关注的是:数量持续上升、流量恢复后仍不下降;连接集中在同一远端地址或业务端口;应用同时出现连接超时、打开文件过多或建立新连接失败;大量连接长时间没有继续进入 TIME_WAIT。

定位连接集中在哪个业务

先查看本地地址、远端地址和端口:

ss -ant state fin-wait-2

统计远端地址:

ss -ant state fin-wait-2 | awk 'NR>1 {print $5}' | sort | uniq -c | sort -nr | head -20

统计本地端口:

ss -ant state fin-wait-2 | awk 'NR>1 {print $4}' | sort | uniq -c | sort -nr | head -20

如果本地使用大量随机高位端口连接固定的远端 443 端口,本机更可能是主动请求方。如果连接集中在本机某个服务端口,还要结合连接方向和进程信息判断,不能只凭端口号下结论。

确认套接字是否仍被进程持有

sudo ss -antp state fin-wait-2

能够看到进程名和 PID 时,应检查对应程序的连接关闭逻辑、请求超时、连接池和优雅退出流程。如果看不到进程信息,可能是权限不足,也可能是连接已经成为不再由用户空间进程引用的孤儿套接字。

继续检查进程的文件描述符:

pid=1234
ls -1 /proc/$pid/fd | wc -l
cat /proc/$pid/limits | grep -i 'open files'

把示例 PID 换成实际值。文件描述符接近上限时,应先查连接是否泄漏。单纯提高上限只能延后故障,不能修复未正确释放连接的代码。

对端为什么迟迟不发送 FIN?

对端应用没有完成关闭

对端可能已收到本机的 FIN,但应用仍在等待数据、阻塞在处理流程中,或者没有按预期关闭套接字。若连接集中在少数可控服务,应同时检查对端日志、线程状态和连接池指标。

代理链路的超时不一致

Nginx、HAProxy、云负载均衡、CDN 和应用服务器可能分别设置空闲超时、读取超时和保持连接时间。一层代理主动关闭后,下游没有及时完成关闭,就可能形成持续较久的半关闭连接。

排查时应按“客户端 → CDN → 负载均衡 → Nginx → 应用”逐层确认。客户端到 CDN 与 CDN 到源站是两组独立 TCP 连接,不能混在一起判断。

长连接或流式业务仍在等待

WebSocket、Server-Sent Events、gRPC 流以及文件传输可能允许一方停止发送后继续接收。此时半关闭状态不一定是故障,需要结合协议设计、连接持续时间和业务日志判断。

网络设备丢弃关闭报文

如果对端已经发送 FIN,但中间防火墙、NAT 或异常链路没有把报文送达,本机仍会继续等待。可在维护窗口对少量目标连接抓包:

sudo tcpdump -nn -i any 'host 203.0.113.10 and tcp port 443'

请替换示例地址并限制抓包范围和时间。重点观察本机 FIN、对端 ACK,以及对端后续是否发送 FIN 或 RST。

tcp_fin_timeout 能解决问题吗?

Linux 的 net.ipv4.tcp_fin_timeout 控制孤儿连接停留在 FIN_WAIT2 的时间。先查看当前值:

sysctl net.ipv4.tcp_fin_timeout

这个参数不是所有 FIN_WAIT2 的统一超时,也不能修复仍被应用引用的套接字。若应用没有正确关闭连接,或者对端业务逻辑一直不结束,仅调整参数通常无法解决根因。

只有确认大量连接已经成为孤儿套接字,并且当前等待时间不适合业务时,才应在测试环境或维护窗口评估调整。例如:

sudo sysctl -w net.ipv4.tcp_fin_timeout=30

这只是示例值,不是通用推荐。修改前应记录原值,修改后观察 FIN_WAIT2 数量、连接错误率、长连接和慢请求。若需永久生效,应通过系统实际使用的 sysctl 配置文件管理,并保留回滚方案。

检查资源是否已经受到影响

ss -s
cat /proc/sys/net/ipv4/ip_local_port_range
cat /proc/sys/fs/file-nr
ulimit -n

FIN_WAIT2 多不等于一定发生端口耗尽。还应检查是否出现 cannot assign requested address、连接建立失败、临时端口高度集中或文件描述符接近上限。扩大端口范围和提高文件描述符限制只能缓解压力,根因仍可能是连接池反复建连、对端不关闭或代理超时冲突。

推荐排查顺序

  1. 连续观察数量,区分短时波动和持续累积。

  2. 按本地端口、远端 IP 和远端端口聚合,定位业务链路。

  3. 使用 ss -p 判断连接是否仍由进程持有。

  4. 检查应用关闭逻辑、连接池、请求超时和优雅退出。

  5. 逐层核对 CDN、负载均衡、反向代理和源站超时。

  6. 必要时抓取少量目标连接,确认 FIN、ACK、RST 的方向。

  7. 确认属于孤儿 FIN_WAIT2 后,再评估 tcp_fin_timeout。

  8. 修改后复查连接状态、错误率和真实业务请求。

常见问题

FIN_WAIT2 越多,问题越严重吗?

不一定。要结合持续时间、流量规模、连接归属和资源压力判断。高并发服务短时出现较多 FIN_WAIT2 可能正常,持续累积且不回落才需要重点排查。

重启应用可以解决吗?

部分由该进程持有的连接可能随退出而消失,但重启会中断业务,也无法修复对端不关闭或超时设计不合理的问题。生产环境应先定位连接归属,并准备流量摘除和回滚方案。

FIN_WAIT2 与 TIME_WAIT 能用同一种方法优化吗?

不能。FIN_WAIT2 是等待对端完成关闭,TIME_WAIT 是关闭握手完成后的保护状态,两者形成阶段和排查重点不同。

结论

处理 FIN_WAIT2 过多时,先确认是否持续累积,再按端口和对端定位业务,随后判断套接字是否仍由应用持有。对端关闭逻辑、代理超时和长连接设计通常比单个内核参数更值得优先检查。只有确认大量连接属于孤儿 FIN_WAIT2,才适合评估 tcp_fin_timeout,并在修改后验证连接状态和业务指标。

参考资料

  1. RFC Editor:RFC 9293,Transmission Control Protocol (TCP),核查日期:2026-09-01。

  2. Linux Kernel Documentation:IP Sysctl,tcp_fin_timeout,核查日期:2026-09-01。

  3. man7.org:ss(8) — another utility to investigate sockets,核查日期:2026-09-01。