服务连不上、老丢包?TCP 网络问题到底该怎么排查?
线上服务连不上,或者接口时不时超时,是日常里最磨人的一类问题。
现象看着都差不多,根因可能差出十万八千里:网卡、路由、防火墙、对端进程、甚至自己代码没关连接。瞎猜没用。
这篇就按一套固定的分层顺序,把 TCP 网络问题从下往上捋一遍,每一步配上能直接抄的命令。
为什么要按分层来排查?
TCP 排查的核心思路是分层定位:从物理链路、网络可达、端口连通,一直查到应用层。
这么做的好处是把范围一刀一刀切小,避免一上来就抓包、淹没在几万行报文里。
我自己的习惯是先问三个问题:能 ping 通吗?端口通吗?连接建起来了吗?
这三关过了,剩下八成是应用层的事。
下面按顺序展开。
第一关:基础连通性,ping 和 mtr
先确认网络层能不能到对端。
## 测连通和丢包率,发 20 个包
ping -c 20 192.168.1.100重点看两个数:丢包率(packet loss)和延迟(time)。
丢包 0%、延迟稳定,说明这层没问题。
如果丢包忽高忽低,或者延迟从几毫秒飙到几百毫秒,那问题大概率在路由路径上。
这时候别用 traceroute,直接上 mtr。
它把 traceroute 和 ping 揉一起,能实时看到每一跳的丢包。
## 持续探测 100 个包,按跳显示丢包和延迟
mtr -rwzbc 100 192.168.1.100看哪一跳开始持续丢包,问题节点基本就锁定了。
有个坑要提醒:中间某一跳显示丢包、但后面的跳又恢复正常,这种通常是那一跳的路由器对 ICMP 限速,不是真丢包,别被它带偏。
只有「从某跳开始一直到终点都丢」才是真问题。
ping 不通不一定代表网络断了。
很多服务器和云主机默认禁掉了 ICMP,ping 不通但 TCP 端口照样能连。
所以 ping 失败时,下一步要直接测端口。
第二关:端口到底通不通?
ping 通了不代表服务能用,端口可能根本没开,或者被防火墙挡了。
## 方式一:nc,-z 只探测不发数据,-v 显示详情
nc -zv 192.168.1.100 3306
## 方式二:telnet,老牌但够用
telnet 192.168.1.100 3306连上了会提示 succeeded 或者 Connected。如果卡住不动最后超时,常见就两种情况:防火墙/安全组把包丢了(表现为没任何响应),或者对端端口压根没监听。
云服务器尤其要查安全组。
我被这个坑过不止一次——本地 iptables 全放开了,结果是云控制台的安全组没放对应端口,排查半天白费劲。
所以云上服务连不通,先去控制台看安全组入站规则,比在机器里翻 iptables 快得多。
本机防火墙也顺手看一眼:
## 查看当前 iptables 规则
iptables -L -n -v第三关:连接状态,ss 是主力
端口通了,就该看连接本身的状态了。
ss 比老的 netstat 快很多,现在基本都用它。
## 看所有 TCP 连接、对应进程,-t TCP -a 全部 -n 不解析 -p 进程
ss -antp
## 统计各状态连接数,这条最常用
ss -ant | awk 'NR>1{print $1}' | sort | uniq -c第二条命令的输出能直接告诉你连接卡在哪个状态上。
TCP 一共有 11 种状态,分别对应三次握手和四次挥手的各个阶段:
| 状态 | 含义 | 出现在 |
|---|---|---|
| LISTEN | 监听端口,等连接 | 服务端 |
| SYN-SENT | 已发 SYN,等回应 | 客户端握手中 |
| SYN-RECV | 收到 SYN 并回了,等 ACK | 服务端握手中 |
| ESTABLISHED | 连接建好,正常通信 | 双方 |
| FIN-WAIT-1 | 主动关闭方发出 FIN | 主动关闭方 |
| FIN-WAIT-2 | 收到对方 ACK,等对方 FIN | 主动关闭方 |
| CLOSE-WAIT | 收到 FIN,等应用关连接 | 被动关闭方 |
| LAST-ACK | 发了 FIN,等最后的 ACK | 被动关闭方 |
| TIME-WAIT | 等 2MSL 再彻底关闭 | 主动关闭方 |
| CLOSING | 双方同时关闭 | 双方 |
| CLOSED | 已完全关闭 | 双方 |
状态名记不全没关系,实战中真正要警惕的就两个:CLOSE-WAIT 和 TIME-WAIT。
大量 CLOSE-WAIT:八成是代码 bug
CLOSE-WAIT 表示对端已经发了 FIN 要关连接,但你这边的应用一直没调用 close。
换句话说,连接该关没关。
这几乎可以断定是代码问题——比如异常路径里漏写了关闭、连接池没回收、或者 defer 没执行到。
CLOSE-WAIT 堆积久了会耗尽文件描述符,最后报 too many open files,服务直接挂。
看到这个状态数量持续涨,别调内核参数,回去查代码里连接有没有正常关闭。
大量 TIME-WAIT:通常是正常现象
TIME-WAIT 出现在主动关闭连接的一方,它要等 2 倍 MSL(Linux 上默认是 60 秒)才彻底释放,目的是确保对端收到最后的 ACK、并让旧连接的残留报文自然过期。
短连接场景下(比如压测、频繁请求的 HTTP 客户端),TIME-WAIT 多到几万个都正常。
一般不用慌。
如果端口确实被占满了,可以谨慎开启 net.ipv4.tcp_tw_reuse,但别去动那个早就被废弃的 tcp_tw_recycle,它在 NAT 环境下会导致丢包,新内核里已经删掉了。
第四关:抓包,tcpdump 兜底
前三关都正常,问题还在,那就只能抓包看报文了。
tcpdump 是最后一道兜底手段。
## 抓 eth0 上和指定 IP、指定端口相关的包,存到文件
tcpdump -i eth0 host 192.168.1.100 and port 3306 -w cap.pcap抓完把 cap.pcap 拖到本地用 Wireshark 打开,比在命令行里盯着看舒服十倍。
重点关注几个信号:有没有大量 retransmission(重传,说明丢包)、有没有 RST(连接被对端强制重置)、SYN 发出去有没有回应(没回应就是握手都没成功)。
举个我遇到的真实例子:接口偶发超时,前面几关全正常,抓包才发现是对端在高负载时直接回 RST 把连接踢了。
这种情况光看连接状态和日志根本看不出来,必须抓包。
关键命令一览
排查时按这个顺序往下走,基本不会漏:
| 阶段 | 命令 | 看什么 |
|---|---|---|
| 连通性 | ping -c 20 IP |
丢包率、延迟 |
| 路由丢包 | mtr -rwzbc 100 IP |
哪一跳开始丢 |
| 端口可达 | nc -zv IP PORT |
端口通不通 |
| 连接状态 | ss -ant | awk 'NR>1{print $1}' | sort | uniq -c |
卡在哪个状态 |
| 进程定位 | ss -antp |
哪个进程占的连接 |
| 防火墙 | iptables -L -n -v |
规则有没有挡 |
| 抓包 | tcpdump -i eth0 host IP -w cap.pcap |
重传、RST、握手 |
常见问题
ping 不通就一定是网络断了吗?
不一定。
很多服务器默认禁用 ICMP,ping 不通但 TCP 端口能正常连。
判断网络通不通,应该用 nc 或 telnet 直接测目标端口,而不是只看 ping 的结果。
CLOSE-WAIT 和 TIME-WAIT 哪个更危险?
CLOSE-WAIT 更需要警惕。
它几乎都是应用代码没正确关闭连接造成的,堆积会耗尽文件描述符导致服务崩溃,得回去查代码。
TIME-WAIT 大多是短连接的正常现象,由主动关闭方产生,一般不影响服务。
ss 和 netstat 有什么区别,用哪个?
两者都能看连接状态,但 ss 直接读内核数据,在连接数大的机器上比 netstat 快得多,新系统也默认装它。
建议优先用 ss,netstat 在很多新发行版里已经不预装了。
云服务器连不通端口,先查哪里?
先查云控制台的安全组入站规则,再查机器里的 iptables。
云环境下安全组拦截最常见,而且在机器内部看不到任何拦截痕迹(包被云网关直接丢了),所以从控制台查更快。
tcpdump 抓的包怎么分析?
用 -w 参数把包存成 .pcap 文件,再拖到本地用 Wireshark 图形化分析。
重点看有没有大量重传(丢包)、RST(连接被重置)、以及 SYN 有没有得到回应(判断握手是否成功)。
写在最后
排查 TCP 问题最忌讳一上来就抓包瞎看。
按 ping → 端口 → 连接状态 → 抓包 的顺序走,大部分问题在前两三步就能定位。连接状态这块,记住 CLOSE-WAIT 查代码、TIME-WAIT 多半正常,就够应付日常九成场景了。
这些命令和判断我都是在自己的 Linux 环境(CentOS 7 和 Ubuntu 22.04)上验证过的,不同发行版参数可能略有差异,遇到不一致以你机器上的 man 手册为准。
如果你在排查时碰到了这篇没覆盖到的诡异现象,或者对某个命令有疑问,欢迎在评论区聊聊~~~
版权声明
未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!
本文原文链接: https://fiveyoboy.com/articles/troubleshoot-tcp-network-issues/
备用原文链接: https://blog.fiveyoboy.com/articles/troubleshoot-tcp-network-issues/