Linux服务器FIN_WAIT1连接过多怎么办?FIN确认延迟、网络丢包与发送队列排查教程
本内容发表于:2026-09-03 15:42:10
浏览量
1040

Linux服务器FIN_WAIT1连接过多排查示意图

在 Linux 服务器上执行 ss -ant 时,如果发现大量连接停留在 FIN_WAIT1,说明本机已经主动发起 TCP 关闭并发送 FIN,但还没有完成这一阶段的确认。少量、短暂出现通常属于正常现象;如果数量持续增长,同时伴随连接超时、发送延迟、端口紧张或服务退出缓慢,就需要检查网络链路、对端响应和本机发送队列。

本文从 TCP 状态转换出发,给出一套可直接执行的排查流程,并说明哪些内核参数与 FIN_WAIT1 有关、哪些常见“优化方法”其实用错了场景。

FIN_WAIT1 是什么状态?

当本机应用程序主动关闭一个已建立的 TCP 连接时,内核会发送 FIN,并从 ESTABLISHED 进入 FIN_WAIT1。正常情况下,对端确认这个 FIN 后,本机进入 FIN_WAIT2;如果对端也同时发送 FIN,连接可能继续进入 CLOSING,最终到达 TIME_WAIT。

因此,FIN_WAIT1 的核心含义不是“程序忘记关闭连接”,而是“本机已经要求关闭,但本机发出的 FIN 尚未完成确认”。这与 CLOSE_WAIT 明显不同:CLOSE_WAIT 通常表示本机已经收到对端 FIN,但应用程序尚未关闭对应套接字。

先判断是否真的异常

业务高峰、批量任务结束、负载均衡摘除实例或服务滚动重启时,FIN_WAIT1 可能短时间增加。排查时不要只看某一秒的总数,应连续观察数量是否下降,并与连接创建速率、错误率和网络重传一起判断。

ss -s
ss -ant state fin-wait-1
watch -n 2 'ss -ant state fin-wait-1 | wc -l'
cat /proc/net/sockstat

如果峰值结束后数量很快回落,通常无需调整内核参数。如果连接长时间不消失,或者数量只增不减,则继续定位进程、目标地址和发送队列。

第一步:找出连接属于哪个进程

ss -oantp state fin-wait-1
lsof -nP -iTCP | grep FIN_WAIT1

-p 用于显示进程信息,通常需要 root 权限;-o 可以查看计时器。如果大量连接集中在同一个 PID,应结合该服务的访问日志、关闭逻辑、超时设置和发布记录继续检查。若看不到进程信息,连接可能已经成为孤儿套接字,也可能是权限不足。

第二步:按本地端口和远端地址聚合

下面的命令可帮助判断问题是集中在某个服务端口,还是集中在某个远端节点:

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

如果远端地址高度集中,优先检查该主机、代理、NAT 网关或负载均衡器。如果多个远端都出现相同现象,而连接集中在一个本地进程,则更可能与应用关闭方式、本机拥塞或发送队列有关。

第三步:检查 Send-Q、重传与拥塞信息

ss -iantp state fin-wait-1
ss -oantp state fin-wait-1

重点关注 Send-Q、重传计时器、拥塞窗口和往返时延。Send-Q 长时间不为零,说明在发送 FIN 之前或同时仍有数据等待发送或确认。可能原因包括对端处理缓慢、接收窗口降为零、链路丢包、拥塞,或者应用在关闭前写入了大量数据。

此时不要急着缩短超时。强行更快回收连接可能让尚未成功交付的数据丢失,并把网络故障变成更隐蔽的业务错误。

第四步:抓包确认 FIN 和 ACK 去向

tcpdump -i any -nn 'tcp[tcpflags] & (tcp-fin|tcp-ack) != 0'
# 已知对端和端口时应缩小范围
tcpdump -i any -nn host 203.0.113.10 and port 443

抓包时应确认四件事:本机是否真的发出了 FIN;FIN 是否发生重传;对端是否返回 ACK;返回的 ACK 是否到达本机。如果 FIN 多次重传而没有回应,应沿链路检查安全组、防火墙、NAT、负载均衡器和对端主机。如果抓包能看到 ACK 到达,但状态仍不转换,则要进一步核对 ACK 序号、连接四元组以及是否存在异常报文或状态错配。

常见原因与处理方向

1. FIN 或 ACK 在网络中丢失

链路拥塞、接口丢包、错误的 MTU、异常路由或中间设备状态超时,都可能导致关闭报文无法完成确认。可结合 ip -s link、ethtool -S、主机监控和两端抓包判断丢包发生在哪一段。

2. 对端失去响应

对端进程卡死、主机重启、连接状态被提前清理,或防火墙直接丢弃后续报文时,本机只能继续重传。若连接集中在少数远端,应让对端同步检查系统日志、连接表和服务状态。

3. 发送队列中仍有数据

应用调用 close() 不代表所有数据已经被对端确认。大响应、慢客户端、零窗口和网络背压都会延长关闭过程。应检查应用写超时、请求体或响应体大小、客户端读取速度,并避免无边界地向慢连接写数据。

4. NAT、负载均衡或防火墙状态不一致

中间设备可能比两端更早清理会话,也可能只允许单向报文通过。检查本机规则时可使用:

nft list ruleset
iptables -S
conntrack -S
conntrack -L -p tcp 2>/dev/null | grep -i fin_wait

生产环境中的 conntrack 表可能很大,列出全部连接前应评估开销。云环境还应检查安全组、网络 ACL、负载均衡空闲超时和 NAT 网关指标。

5. 服务关闭或发布产生连接洪峰

滚动发布时一次性终止大量长连接,会让主动关闭状态集中出现。更稳妥的方式是先停止接收新流量,等待已有请求排空,再结束进程;同时为 WebSocket、HTTP/2、数据库连接池等长连接设置合理的优雅退出时间。

FIN_WAIT1 会导致端口耗尽吗?

有可能,但要看本机是否作为客户端大量主动建连,以及连接是否占用了同一组源地址和目标四元组。可检查临时端口范围与当前连接规模:

sysctl net.ipv4.ip_local_port_range
ss -ant | awk 'NR>1 {print $1}' | sort | uniq -c
cat /proc/net/sockstat

端口紧张的根治方向通常是减少不必要的短连接、启用并正确配置连接复用、扩大客户端实例或源 IP,并解决 FIN 无法确认的原因。仅扩大临时端口范围可以增加余量,但不能修复丢包或对端失联。

内核参数应该怎么判断?

不要把 tcp_fin_timeout 当作 FIN_WAIT1 清理开关

net.ipv4.tcp_fin_timeout 在 Linux 文档中主要用于孤儿连接停留在 FIN_WAIT2 的时间。它不是专门解决 FIN_WAIT1 堆积的参数。看到 FIN_WAIT1 就盲目把该值调小,往往不会解决根因。

谨慎评估 tcp_retries2

net.ipv4.tcp_retries2 影响已建立连接在放弃前允许的 TCP 重传次数,也会影响连接在持续无响应时等待多久。降低它可能更快释放异常连接,但也会让高延迟、短时拥塞或跨境链路上的正常连接更容易被提前中止。

sysctl net.ipv4.tcp_retries2
sysctl net.ipv4.tcp_orphan_retries

修改前应记录基线,在测试环境或小范围实例验证,并准备回滚。不要从网络文章复制一组“通用最优值”直接应用到生产环境。

推荐的排查顺序

  1. 连续观察 FIN_WAIT1 数量,确认是短时峰值还是持续堆积。

  2. 使用 ss -oantp 定位进程、端点、Send-Q 和计时器。

  3. 按远端地址与本地端口聚合,缩小故障范围。

  4. 在明确四元组后抓包,确认 FIN、ACK 和重传情况。

  5. 核查应用关闭逻辑、慢连接、优雅退出和超时设置。

  6. 检查主机防火墙、conntrack、NAT、负载均衡及对端状态。

  7. 确认根因后再评估内核参数,并通过灰度测试验证影响。

FIN_WAIT1 与其他关闭状态有什么区别?

状态含义优先排查
FIN_WAIT1本机已发送 FIN,尚未完成确认丢包、对端响应、Send-Q、中间设备
FIN_WAIT2本机 FIN 已确认,等待对端 FIN对端是否关闭、孤儿连接
LAST_ACK本机被动关闭后已发 FIN,等待最终 ACK对端 ACK、重传、链路状态
CLOSE_WAIT收到对端 FIN,但本机应用尚未关闭应用连接泄漏与关闭逻辑
TIME_WAIT主动关闭流程基本完成,等待旧报文失效短连接规模、端口复用与连接池

常见问题

FIN_WAIT1 一多就代表服务器被攻击吗?

不一定。它更常见于对端无响应、链路丢包、发送队列积压或批量关闭连接。是否存在攻击需要结合流量来源、连接创建速率、防火墙日志和业务行为判断。

重启服务能解决吗?

重启可能暂时减少部分连接或转移流量,但不会修复中间设备丢包、对端失联和错误的关闭策略。重启前应保留 ss 输出、抓包和系统日志,否则关键证据会消失。

可以直接调小 tcp_retries2 吗?

不建议直接修改。该参数会影响正常已建立连接的失败判定,高延迟或短暂抖动环境尤其敏感。应先证明连接确实因持续重传而卡住,再进行小范围验证。

如何判断是本机问题还是对端问题?

最可靠的方法是两端同时抓包。如果本机发出 FIN,但对端没有收到,应检查中间链路;如果对端收到并发出 ACK,但本机没有收到,应检查返回路径;如果 ACK 已到达本机,则继续核对序号、四元组和内核状态。

结论

大量 FIN_WAIT1 的关键不是立即“清连接”,而是确认本机发送的 FIN 为什么没有被正常确认。先用 ss 找到进程、端点、Send-Q 和计时器,再通过抓包区分对端无响应、网络丢包、发送积压和中间设备状态问题。只有在证据表明默认重传等待不适合业务时,才应谨慎评估相关内核参数。

参考资料

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

  2. Linux ss(8) manual page,核查日期:2026-09-03

  3. Linux tcp(7) manual page,核查日期:2026-09-03

  4. Linux kernel IP sysctl documentation,核查日期:2026-09-03