作为搞Linux排障的老兵,我写“三步法”上篇的时候,重点把物理层、数据链路层和网络层(IP层)的家底翻了个底朝天。那会儿主要解决的是“路通不通”的问题,比如网线松了、ARP表乱了、路由不对、ping不通这类基础故障。但是干过实战的兄弟都知道,最磨人的不是网络不通,而是“网络通,但服务就是不行”。TCP连接卡在半死不活的状态、DNS解析时好时坏、HTTP请求超时但端口明明在监听、测试环境一切正常一到生产就抽风……这些问题一旦牵涉到传输层和应用层,就不是光靠看IP地址和路由表能解决的了。
这篇“下篇”,咱们把7层模型的最后两块硬骨头啃透。我会从传输层的TCP状态机和端口连通性诊断入手,再往上走到应用层的DNS、HTTP、TLS握手排查,最后落地到一套完整的排障流程总结。整套方法论是我这些年在一线服务器上实战总结出来的,不是教科书式的理论堆砌,而是能直接对着问题“抄作业”的操作指南。对刚入门的运维、开发,以及被线上故障折腾到头秃的兄弟,这篇都有很强的参考价值。
1. 传输层排查:先确认“路通没通”
网络层给你画了一张“地图”,告诉你IP路径是通的。但数据能不能真正送到对端进程手里,取决于传输层。TCP协议是面向连接的,它的三次握手、四次挥手、状态机转换,是整个传输层排障的核心。我常说一句话:**“应用层的报错千奇百怪,传输层的状态却能一锤定音。”**排查传输层问题时,我们不是靠猜,而是靠状态。连接是SYN_SENT还是ESTABLISHED?是大量TIME_WAIT堆积还是CLOSE_WAIT泄漏?这些状态背后都有对应的“剧情”,你能看懂它们,就赢了一半。
1.1 三次握手和TCP状态机:从SYN_SENT看出问题
TCP三次握手的过程理论上是这样:客户端发SYN,服务端回SYN+ACK,客户端再回ACK,连接就建起来了。听起来简单,但实际排障时的状态变化才是关键。假设我们用telnet或者nc去访问一个远程端口,如果连接卡住,最直观的判断方式就是看客户端这边连接是什么状态。一个常见场景是客户端用netstat -ant | grep 8080看到大量SYN_SENT,这代表客户端发了SYN包,却一直没收到对端的SYN+ACK响应。
这个现象背后基本有三种可能:目标IP根本不存在(或不可达)、目标端口没有服务监听、中间防火墙/安全组丢弃了SYN包。怎么快速区分呢?用tcpdump -i eth0 host 目标IP and tcp port 8080在发包的同时抓包。如果只看到出站的SYN,没有入站SYN+ACK,大概率是防火墙直接丢了,连RST都不回。如果对端回的是RST,说明服务本来就没监听,这个端口是关闭的。如果SYN+ACK正常返回但客户端就是报错,那就得回来看本机的iptables规则,是不是有OUTPUT链丢弃了什么。
这里要提一个经常被忽略的点:SYN重传策略。Linux内核默认net.ipv4.tcp_syn_retries = 6,意味着首次SYN发出后,如果收不到响应,会隔1秒重试,之后指数退避,总共重试6次。如果服务端响应慢,客户端会表现出“连接卡了1分多钟才报错”的现象。有个经典排查场景:客户端报“Connection timed out”,抓包发现客户端一直在重传SYN,而远端服务器CPU跑满,根本没机会处理新连接。这时候你问题根源就不在网络上而在服务端的资源上,但症状表现为“连接超时”。看懂状态和重传行为,能帮你精准定位。
再说一说服务端视角的建立连接。服务器上监听socket会经历LISTEN状态,收到SYN后进入SYN_RECV,这里牵涉到半连接队列(SYN Queue)和全连接队列(Accept Queue)。如果系统日志或netstat -s里出现SYN重传和丢包异常,并且客户端说连接超时,但服务端端口是LISTEN状态,那基本就是队列满了。这种故障有个很有意思的特征——本地连本地端口是好的,远程连就超时。原因在于本地回环不走网卡,不经过防火墙,也不会进同一个队列处理路径。
1.2 端口连通性与监听状态:ss和nc是最终裁判
排查完状态机,接下来要做的是确认“端口到底听没听”。老运维习惯用netstat,但我更推荐`s
