
在 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
推荐的处理顺序
连续观察 LAST_ACK 数量,确认是否持续堆积;
按本地端口、远端地址和进程聚合;
检查应用重启、超时和集中关闭连接的日志;
使用
ss -o和ss -i查看定时器与重传;抓包确认 FIN 是否发出、最终 ACK 是否返回;
核对防火墙、NAT、负载均衡器和连接跟踪超时;
最后再评估内核参数,并先进行灰度验证。
常见问题
少量 LAST_ACK 正常吗?
正常。TCP 关闭需要报文交换,采样时看到少量 LAST_ACK 并不代表故障。只有数量持续增长、停留时间异常或业务出现错误时,才需要深入排查。
重启服务能清掉 LAST_ACK 吗?
重启可能暂时改变部分连接,但不能证明根因已经解决。如果问题来自对端不回复、防火墙丢包或超时不一致,服务恢复后仍可能再次出现。
LAST_ACK 多就是应用 Bug 吗?
不一定。LAST_ACK 通常说明本机应用已经执行关闭。应用关闭时序可能存在问题,但对端异常和网络回程丢包同样常见。
可以直接调小 tcp_retries2 吗?
不建议直接修改。该参数会影响更广泛的 TCP 重传行为,过低可能让正常连接在短暂拥塞时提前断开。应先取得抓包与重传证据,再做灰度测试。
结论
大量 LAST_ACK 的核心含义不是“本机忘记关闭连接”,而是本机已经发送最后的 FIN,却没有及时收到对端确认。有效的排查路径是先找出受影响的端口、对端和进程,再通过定时器、重传计数与抓包判断 ACK 丢在对端、链路还是本机。内核参数只能作为最后的风险控制手段,不能替代对连接关闭链路的定位。
参考资料
RFC 9293: Transmission Control Protocol (TCP),核查日期:2026-09-02
Linux man-pages: ss(8),核查日期:2026-09-02
Linux man-pages: tcp(7),核查日期:2026-09-02
Linux Kernel Documentation: IP Sysctl,核查日期:2026-09-02