Linux服务器LAST_ACK连接过多怎么办?对端未确认、TCP重传与连接关闭排查教程
本内容发表于:2026-09-02 14:17:51
浏览量
1054

Linux服务器LAST_ACK连接状态与TCP重传排查示意图

在 Linux 服务器上执行 ss -ant 时,如果发现大量连接长期停留在 LAST-ACK,通常意味着本机应用已经主动关闭连接并发送了 FIN,但迟迟没有收到对端对这个 FIN 的确认。少量、短暂出现的 LAST_ACK 属于 TCP 正常关闭过程;需要重点排查的是数量持续增长、相同对端反复出现,或者同时伴随连接超时、文件描述符紧张和业务错误的情况。

本文介绍 LAST_ACK 的含义,以及从连接数量、端口、进程、抓包、防火墙到内核参数的完整排查顺序。

LAST_ACK 是什么状态?

按照 TCP 关闭流程,本机先收到对端的 FIN 并回复 ACK,此时进入 CLOSE_WAIT。应用随后调用 close(),内核向对端发送自己的 FIN,连接便进入 LAST_ACK。收到对端对这个 FIN 的最终 ACK 后,连接才会彻底关闭。

LAST_ACK 的核心含义是:本机应用已经执行关闭,内核正在等待对端确认最后一个 FIN。

状态含义排查重点
CLOSE_WAIT对端已关闭,本机应用尚未关闭应用连接泄漏、线程阻塞
FIN_WAIT1本机已发送 FIN,等待确认网络丢包、对端响应
FIN_WAIT2本机 FIN 已确认,等待对端 FIN对端未关闭、长连接设计
LAST_ACK本机发送最后的 FIN,等待 ACK对端异常、回程丢包、重传

先判断:短暂波动还是持续堆积?

不要只看一次命令结果。先连续观察 LAST_ACK 数量:

watch -n 2 "ss -ant state last-ack | tail -n +2 | wc -l"

同时汇总全部 TCP 状态:

ss -ant | awk 'NR>1 {count[$1]++} END {for (s in count) print s, count[s]}' | sort

如果数量只在业务高峰短暂增加,随后快速下降,一般无需调整内核。若连接连续数分钟甚至更久只增不减,应继续确认连接集中在哪个端口、对端和进程。

第一步:找出连接集中在哪些端口和对端

ss -ant state last-ack

# 按远端地址和端口统计
ss -Hant state last-ack | awk '{print $5}' | sort | uniq -c | sort -nr | head -20

# 按本地地址和端口统计
ss -Hant state last-ack | awk '{print $4}' | sort | uniq -c | sort -nr | head -20

如果连接集中在某个反向代理、负载均衡器、API 网关或固定客户端,应优先检查该对端是否重启、过载或网络中断。若连接分散在大量公网地址,则要结合访问日志判断是否存在扫描、异常客户端或链路质量问题。

第二步:确认连接属于哪个进程

sudo ss -antp state last-ack
sudo lsof -nP -iTCP -sTCP:LAST_ACK

重点记录进程名、PID、本地端口和远端地址。与 CLOSE_WAIT 不同,LAST_ACK 通常说明应用已经调用关闭操作,因此不能只按“应用忘记 close”的思路处理,还要关注进程退出方式、连接关闭时序、对端实现和网络回程。

如果大量连接都属于同一个服务,再检查近期日志:

journalctl -u your-service --since "30 minutes ago"
dmesg -T | tail -100

第三步:观察定时器和重传

sudo ss -oantp state last-ack
sudo ss -iantp state last-ack

如果同一批连接的重传次数持续增加,说明本机正在重发 FIN,却没有收到有效 ACK。常见原因包括:

  • 对端进程或主机异常退出,无法回复;

  • 对端回复的 ACK 在回程链路中丢失;

  • 安全组、防火墙、ACL 或 NAT 设备提前删除会话;

  • 负载均衡器两侧的空闲超时不一致;

  • 链路拥塞、路由不对称或连接跟踪异常。

第四步:抓包确认 FIN 和 ACK

以下命令以本地服务端口 443 和指定对端为例:

sudo tcpdump -i any -nn -s 0 'host 203.0.113.10 and tcp port 443' -w /tmp/last-ack.pcap

在 Wireshark 中观察本机 FIN 是否多次重传、对端是否发送 ACK,以及 ACK 是否到达正确的服务器。如果本机连续发送 FIN 却没有任何回应,问题更可能位于对端或中间网络。如果 ACK 已到达网卡但连接没有结束,则要进一步核对四元组、序列号、ACK 号、NAT 和网络命名空间。

第五步:检查防火墙、NAT 和连接跟踪

sudo nft list ruleset
sudo iptables -S
sudo conntrack -L -p tcp 2>/dev/null | grep -E 'LAST_ACK|src=|dst=' | head

如果业务经过云负载均衡、NAT 网关或硬件防火墙,还要核对两端的空闲超时、会话保持和连接跟踪时间。真正丢弃关闭报文的设备可能不在 Linux 服务器上。

tcp_fin_timeout 能解决 LAST_ACK 堆积吗?

通常不能直接解决。net.ipv4.tcp_fin_timeout 主要控制孤儿连接在 FIN_WAIT2 状态保留的时间,并不是 LAST_ACK 的专用超时参数。仅仅调小它,不能替代对 LAST_ACK 重传和对端不确认问题的定位。

LAST_ACK 中 FIN 的重传与 TCP 重传机制有关,net.ipv4.tcp_retries2 会影响已建立连接放弃前允许的重传时间范围。但该参数影响较广,设置过低可能让正常但暂时拥塞的连接过早失败。

sysctl net.ipv4.tcp_fin_timeout
sysctl net.ipv4.tcp_retries2
sysctl net.ipv4.tcp_orphan_retries
sysctl net.ipv4.tcp_max_orphans

修改参数前应记录当前值、连接持续时间、丢包与重传证据,并先在测试环境验证。缩短回收时间可能降低表面连接数,但也可能掩盖对端异常或网络丢包。

LAST_ACK 会导致端口耗尽吗?

LAST_ACK 会占用内核套接字资源,数量很大时可能增加内存、socket 表和文件描述符压力。但客户端临时端口耗尽更常见于大量主动外连以及 TIME_WAIT、ESTABLISHED 等状态。应结合下面的指标判断:

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

推荐的处理顺序

  1. 连续观察 LAST_ACK 数量,确认是否持续堆积;

  2. 按本地端口、远端地址和进程聚合;

  3. 检查应用重启、超时和集中关闭连接的日志;

  4. 使用 ss -o 和 ss -i 查看定时器与重传;

  5. 抓包确认 FIN 是否发出、最终 ACK 是否返回;

  6. 核对防火墙、NAT、负载均衡器和连接跟踪超时;

  7. 最后再评估内核参数,并先进行灰度验证。

常见问题

少量 LAST_ACK 正常吗?

正常。TCP 关闭需要报文交换,采样时看到少量 LAST_ACK 并不代表故障。只有数量持续增长、停留时间异常或业务出现错误时,才需要深入排查。

重启服务能清掉 LAST_ACK 吗?

重启可能暂时改变部分连接,但不能证明根因已经解决。如果问题来自对端不回复、防火墙丢包或超时不一致,服务恢复后仍可能再次出现。

LAST_ACK 多就是应用 Bug 吗?

不一定。LAST_ACK 通常说明本机应用已经执行关闭。应用关闭时序可能存在问题,但对端异常和网络回程丢包同样常见。

可以直接调小 tcp_retries2 吗?

不建议直接修改。该参数会影响更广泛的 TCP 重传行为,过低可能让正常连接在短暂拥塞时提前断开。应先取得抓包与重传证据,再做灰度测试。

结论

大量 LAST_ACK 的核心含义不是“本机忘记关闭连接”,而是本机已经发送最后的 FIN,却没有及时收到对端确认。有效的排查路径是先找出受影响的端口、对端和进程,再通过定时器、重传计数与抓包判断 ACK 丢在对端、链路还是本机。内核参数只能作为最后的风险控制手段,不能替代对连接关闭链路的定位。

参考资料

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

  2. Linux man-pages: ss(8),核查日期:2026-09-02

  3. Linux man-pages: tcp(7),核查日期:2026-09-02

  4. Linux Kernel Documentation: IP Sysctl,核查日期:2026-09-02