1. 先把分层的边界划清楚不然后面全是糊涂账TCP/IP 五层模型这套东西我最早是在课本上背的背完就忘真正记住是从一次线上故障开始的业务反馈跨机房调用偶发超时运维说网络没丢包开发说代码没问题两边对着监控看了两天最后发现问题卡在链路层——某台设备的双工模式协商错了半双工下冲突退避导致偶发延迟尖刺。那次之后我才明白分层不是为了考试是为了让你在出问题时能把锅精确地甩到某一层而不是一群人围着屏幕互相猜。物理层到传输层这四层覆盖了绝大多数人日常会遇到的网络问题。物理层管的是电信号、光信号怎么在有形介质上跑数据链路层管的是同一段链路上两个相邻设备怎么把比特凑成帧、怎么识别彼此网络层管的是跨网段怎么找到路传输层管的是端到端两条进程之间怎么保证数据不丢不乱。再往上的应用层是业务自己的事往下就是这四层的地盘。你要做的排障、调优、选型九成落在这一区间。这篇内容适合三类人一是刚接触网络、被子网掩码MTU滑动窗口这些词绕晕的新手二是写过几年业务代码、需要自己定位接口超时到底卡在哪的开发者三是需要做机房布线、设备选型、链路验收的实施人员。我不打算按教材顺序从信号编码一路念到拥塞控制算法那样读完还是不会用。我按这一层到底解决什么问题、关键参数怎么算、坑在哪的顺序来讲每个结论都尽量给出可复现的计算过程或者实测现象。提醒一句分层是逻辑模型不是物理隔离。真实设备往往一次处理好几层的活比如一块网卡既做物理层编码又做链路层组帧。排障时按层切分只是给你一个有序的检查顺序别把它当成硬边界。1.1 每一层到底交付了什么理解分层最高效的方式是看每一层向上交付的产物是什么。物理层交付的是一条能承载比特流的通道它不关心你发的是 0 还是 1只保证两端的电平、光功率、时序对得上。链路层交付的是一个帧帧里带了源和目的 MAC 地址还有校验字段它保证同一广播域内的两台设备能互相认出来、能发现传输错误。网络层交付的是一个包包里带源和目的 IP它保证跨网段能寻址、能转发、能在复杂的拓扑里选一条路。传输层交付的是一个端到端的可靠或不可靠通道用端口号区分不同进程用序号、确认、重传、窗口这些机制处理乱序、丢失和流量匹配。这个交付物的视角在排障时特别好用。你抓到一个包先看它停在哪一层如果连帧都没成形问题在物理层或者链路层协商如果帧正常但目的 MAC 是广播地址说明 ARP 没解出来问题在网络层的地址解析如果 IP 包正常但 TTL 异常小说明路由环路或者被中间设备重定向了如果 TCP 一直在重传同一个序号说明丢包发生在接收端之前或者窗口被压到了零。一层一层往上剥比凭感觉猜快得多。我在带新人的时候会让他们做一个练习拿一台机器手动把网线拔掉、把 IP 配错、把网关配错、把防火墙规则加错四种情况分别观察现象记录哪些命令还能用、哪些报什么错。做完这一轮他们对哪层出问题长什么样就有了肌肉记忆。这个练习成本很低但比看十遍理论管用。1.2 为什么实际工程里必须按层定位因为跨层排查的信息是不对称的。你在应用层看到一个请求超时这个现象在四层里可能有完全不同的成因物理层光衰过大导致误码率升高链路层 MTU 不匹配导致大包被丢网络层路由不对称导致回程走了另一条路传输层窗口太小导致吞吐上不去。如果你只盯着应用日志永远只能看到超时两个字看不到背后到底是哪一环断了。按层定位的另一个好处是能快速排除。物理层的检查通常最快也最便宜看端口灯、看光功率、看误码计数。如果物理层没问题链路层的检查也不贵看 MAC 表、看 VLAN 配置、看双工协商。真正耗时的是网络层往上的排查因为它涉及的配置多、路径长。所以正确的顺序是从下往上先用低成本手段排除掉大部分可能性再往贵的地方查。很多人习惯反过来一上来就怀疑代码、怀疑中间件花几个小时打完日志才发现是网线水晶头没压好。还有个容易被忽略的点分层能帮你判断这个问题归不归你管。做业务的只需要负责到传输层之上的连接建立和超时设置物理层的误码、链路层的环路、网络层的路由策略那是另一拨人的职责范围。把问题定位到层等于把工单派给了对的人这在多人协作的场景里比技术本身更值钱。2. 物理层所有问题的起点也最容易被跳过物理层看着简单其实是坑最集中的地方因为它的故障表现最像别的问题。光衰大一点表现出来是 TCP 大量重传你会以为是拥塞双绞线太长表现出来是间歇性丢包你会以为是交换机性能不够网线用了劣质水晶头表现出来是速率协商不到千兆你会以为是网卡驱动。我处理过的网络故障里物理层原因占比大概在三成以上但排查时被第一个怀疑的概率不到一成。物理层关心的核心指标其实就几个介质类型、传输距离、信号质量、编码方式、接口标准。双绞线这一类超五类在 100 米内跑千兆是常规操作六类在同样距离上余量更大但注意这个 100 米是信道长度包含两端跳线、配线架、模块在内的总长度不是两点之间的直线距离。我见过机房改造时把桥架绕了一大圈实际布线长度到了一百三十多米结果就是白天业务低峰还行一到大流量就丢包。光纤这边单模和多模的选择很多人搞混。单模的芯径小、只传一个模式适合长距离几公里到几十公里都没问题多模芯径大、多个模式同时传模式色散限制了距离常规千兆多模在几百米量级。选型的判断依据不是哪个更先进而是距离、成本、现有布线。短距离用单模光模块是浪费钱长距离用多模根本跑不通。这个逻辑跟选网线是一样的够用、留余量别为了参数好看多花钱。2.1 双绞线与光链路的选型参数怎么定先说双绞线。你真正需要确认的只有三件事类别、长度、屏蔽与否。类别决定带宽上限超五类支持千兆到 100 米六类在同样距离上串扰余量更好、支持到 250MHz六类以上还有超六类、七类这些但对绝大多数办公和机房场景六类已经够了。长度按前面说的信道总长算超过 90 米的水平布线就该考虑中间加设备或者改光纤。屏蔽与否看环境强电走线密集、变频设备多的车间里用屏蔽线普通办公区非屏蔽就行屏蔽线如果接地没做好反而比非屏蔽更容易出问题。光纤这边要算的是光功率预算。链路总损耗等于光纤本身的衰减加上各个连接点、熔接点的损耗再留出余量。多模光纤在 850nm 窗口的衰减典型值是每公里 3dB 左右单模在 1310nm 窗口是每公里 0.4dB 左右。每个连接器大概 0.5dB每个熔接点 0.1 到 0.2dB。把这些加起来跟模块的发射功率和接收灵敏度一对就能判断这条链路能不能通。很多光模块插上灯不亮的问题本质是预算算不过来不是模块坏了。介质类型典型距离上限关键约束常见误判现象超五类双绞线100 米信道串扰、长度超限高速率下间歇丢包六类双绞线100 米信道施工弯折半径速率协商降级多模光纤数百米模式色散、连接损耗链路时通时断单模光纤数公里以上光功率过载或不足误码计数缓慢增长注意光模块的接收端有过载点发射功率太强、距离太近也会出问题。短距离直连时看到误码不要只往信号弱上想也可能是信号太强加个衰减器反而好了。2.2 编码方式为什么会影响你看到的现象编码这件事听起来很底层但它直接决定了你在抓包时看到的错误形态。早期的以太网用曼彻斯特编码每个比特中间都有一次电平跳变好处是接收端容易提取时钟坏处是效率只有 50%。后来的百兆用 4B/5B把 4 位数据映射成 5 位符号保证有足够的跳变供时钟恢复效率 80%。千兆用 8B/10B万兆往上用 64B/66B开销越来越小。为什么要懂这个因为不同的编码方式对错误的敏感度不一样。8B/10B 这类编码有运行不一致的检测机制如果链路误码导致符号错位接收端能比较快地发现并报错而某些编码下误码可能表现成一串看起来合法的数据错误被吞掉等到上层校验才发现此时已经丢了一个包。这解释了一个常见困惑为什么有的链路误码率不高但业务侧感受到的丢包却很规律。底层检测不出来上层就成了背锅的。实操上你不需要手算编码但要知道去哪里看误码。交换机的端口统计里通常有 CRC 错误计数、对齐错误计数、FCS 错误计数这几个字段。CRC 错误和 FCS 错误增长基本可以锁定物理层或者链路层的信号质量问题对齐错误增长往往是速率或者编码协商出了问题。这些计数器是累计值看绝对值没意义要看增长率。我的习惯是间隔五分钟采两次算出差值如果每分钟都在涨那就是硬故障别犹豫换线换模块换端口从上往下换一遍。3. 数据链路层帧、MAC 和那些说不清的二层问题链路层是最容易被误解的一层因为二层问题这个词在运维圈里被滥用了很多时候被当成我查不出来所以说是二层。真实的链路层职责很清晰把物理层送来的比特流切成帧加上源和目的 MAC 地址加一个校验字段然后交给网络层同时负责同一广播域内的寻址ARP 就在这层的边界上以及用 VLAN 把一个大广播域切成若干小的。以太网帧的结构值得背下来因为排障时抓包第一眼看的就是它。标准帧是目的 MAC 六字节、源 MAC 六字节、类型或长度两字节然后是 46 到 1500 字节的载荷最后四字节 FCS 校验。前面还有八个字节的前导码和帧起始定界符后面有帧间隙。最小帧 64 字节这个数字不是随便定的它是为了保证在最早期的共享介质网络上发送方在帧发完之前一定能检测到冲突。帧太小会被判为残帧丢弃太大超过 MTU 会被分片或者丢弃。MTU 是链路层最容易出事的参数。以太网的标准 MTU 是 1500 字节这个数字加上 14 字节帧头、4 字节 FCS是 1518 字节如果带 VLAN 标签再加 4 字节到 1522如果链路层做了其他封装还会更长。很多隧道技术会在原有帧外面再包一层导致实际可用 MTU 变小。如果你在两台设备之间跑了隧道却没有相应调小 MTU结果就是小包能通、大包全丢——因为大包被分片或者被中间设备直接丢弃而很多应用的握手包很小所以能连上但传不了数据。3.1 MTU 与分片的实际计算我拿一个最常见的场景算一遍。假设你在两个网段之间跑了一条隧道隧道封装会增加 24 字节的头部开销。原来链路的 MTU 是 1500封装之后内层能承载的最大报文就变成了 1500 减去 24等于 1476。如果你内层设备的 MTU 还设成 1500那么一个 1500 字节的包进隧道之后总长变成 1524超过了外层链路的 1500这时候要么被分片要么被丢弃。分片本身不是灾难但它有三个副作用一是增加中间设备的负担分片和重组都要消耗资源二是只要其中一个分片丢了整个原始报文就得重传重传代价被放大三是有些设备或者安全策略直接丢弃分片包表现就是完全不通。所以现代网络的通行做法是尽量避免分片靠路径 MTU 发现机制来协商。路径 MTU 发现的原理不复杂发送方先把包设成不允许分片标志然后按自己认为的 MTU 发出去。如果路径上某个环节的 MTU 更小它会给发送方回一个需要分片但被禁止的 ICMP 消息里面带上它自己的 MTU 值。发送方收到后调小 MTU 重发。问题在于这条 ICMP 消息经常被各种策略拦掉发送方收不到反馈就一直按大包发一直失败形成黑洞。注意遇到小包通、大包不通的现象第一个怀疑对象就是 MTU 黑洞。验证方法很简单用不允许分片的标志发一个逐步增大长度的探测包找到那个临界长度就知道路径上的真实 MTU 是多少。3.2 ARP、VLAN 和广播域的边界ARP 的作用是把 IP 地址翻译成 MAC 地址它工作在广播域内。这个广播域内的限制是很多问题的根源。跨网段的通信主机不会直接 ARP 目标地址而是 ARP 网关地址然后由网关转发。如果网关的 ARP 表项老化或者被攻击者伪造表现就是能 ping 通网关但上不了外网或者时通时不通。VLAN 是把一个物理交换机切成多个逻辑广播域的手段。它的价值不只是隔离广播风暴更重要的是划清故障边界。一个 VLAN 里的广播泛洪不会影响到另一个 VLAN一个 VLAN 里的地址冲突也不会波及别的部门。但 VLAN 配置有几个容易出错的地方一是 Trunk 口允许通过的 VLAN 列表漏配一个就走不通二是 native VLAN 两端不一致会导致带标签的帧和不带标签的帧互相错认三是 VLAN 间的路由没配跨 VLAN 通信直接断。我踩过最隐蔽的一个坑是生成树协议引起的。两台交换机之间有多条链路生成树为了防环会阻塞掉其中一条正常情况下这没问题。但有一次链路质量不好端口反复 Up/Down每次状态变化都触发一次拓扑重算重算期间所有端口短暂停止转发业务侧感受到的就是每隔几十秒卡一下。这种问题的特征是周期性、全 VLAN 受影响、抓包能看到大量拓扑变更通知。解决办法要么是修链路要么是启用边缘端口快速收敛要么直接上链路聚合把多条物理链路捆成一条逻辑链路。二层故障现象常见原因定位手段同一 VLAN 内互 ping 不通端口 VLAN 归属错、MAC 表未学习查 MAC 地址表、查端口配置跨 VLAN 不通网关未配、Trunk 未放行逐跳查网关和 Trunk 列表周期性全网卡顿生成树拓扑震荡查拓扑变更计数、查端口 Up/Down 日志大包不通小包通MTU 不匹配用禁止分片标志探测临界长度4. 网络层地址、路由和转发的确定性网络层是我个人觉得最工程的一层因为它的行为高度确定给一个目的地址查表按最长前缀匹配转发。没有握手没有重传没有窗口就是一个纯粹的转发决策。这种确定性带来的好处是只要能拿到路由表你就能推演出包的走向坏处是一旦推演和实际不符说明有你看不到的东西在起作用比如策略路由、NAT、或者中间设备做了额外处理。IP 报文头里几个字段值得单独说。TTL 决定了一个包最多能经过多少跳每过一个三层设备减一减到零就丢弃并回一个超时消息。这个机制本来是为了防止环路里的包永远转下去实际排障时它非常好用你用逐步增大 TTL 的方式发包每一跳都会回一个超时消息把这些消息的源地址收集起来就得到了完整的路径。这就是路由追踪的原理。标识、标志、片偏移这三个字段负责分片和重组。标识用来标记同一个原始报文的所有分片标志位里的不允许分片就是路径 MTU 发现的关键片偏移告诉接收方这个分片在原报文里的位置。分片只在必要的时候发生而且只在 IPv4 里由中间设备做IPv6 把这活交给了发送方中间设备不再分片。协议号字段告诉你载荷是什么1 是 ICMP6 是 TCP17 是 UDP。抓包时如果看到协议号是 47 或者 50 这类说明跑的是隧道封装这时候 MTU 的问题就要特别注意了因为外层封装吃掉了不少空间。4.1 子网划分的手算过程和常见误区子网划分这事很多人靠计算器我觉得至少手算过一遍再靠工具。原理很简单IPv4 地址 32 位掩码决定前多少位是网络部分剩下的是主机部分。掩码里 1 的个数就是前缀长度比如 255.255.255.0 是 24 个 1写成 /24。主机位数等于 32 减去前缀长度可用主机数等于 2 的主机位数次方减 2减掉的是网络地址和广播地址。拿一个具体例子走一遍。假设给你 10.20.30.0/24要切成四个大小相同的子网。四个子网需要借两位因为 2 的 2 次方等于 4。前缀从 24 变成 26主机位剩 6 位每个子网 64 个地址可用主机 62 个。子网网络地址可用范围广播地址110.20.30.0/2610.20.30.1 到 10.20.30.6210.20.30.63210.20.30.64/2610.20.30.65 到 10.20.30.12610.20.30.127310.20.30.128/2610.20.30.129 到 10.20.30.19010.20.30.191410.20.30.192/2610.20.30.193 到 10.20.30.25410.20.30.255这个表我建议每个做网络的人至少自己手推三遍推到不用想就能写出来。因为排障时经常需要现场判断这个地址和那个地址在不在一个网段手算比掏手机快。常见误区有三个。第一个是把子网数量和可用主机数量搞反借位的时候算错。第二个是忘了减掉网络地址和广播地址导致分配时冲突。第三个是跨子网通信时忘了配网关主机能 ARP 到自己网段内的设备但出不去表现出来是只能访问内网不能访问外网很多人第一反应是防火墙问题其实是网关没配。还有个更隐蔽的掩码写错但不报错。比如本该是 /24 写成了 /23网段范围扩大了一倍两个原本隔离的网段变成同一个广播域短期内可能看不出问题等到广播量上来了才发现。这种错误在多设备手工配置的环境里特别常见我的做法是配置完立刻用地址计算工具反推一遍确认网络地址、广播地址、可用范围三个值都对得上。4.2 路由表和最长前缀匹配的实际含义路由表的核心规则是最长前缀匹配意思是当多条路由都能匹配目的地址时选前缀最长的那条。这条规则解释了为什么默认路由 0.0.0.0/0 永远排在最后——它的前缀长度是零谁都比它长。也解释了为什么明细路由能覆盖汇总路由因为明细路由的前缀更长。举个实际例子。路由表里有三条10.0.0.0/8 指向 A10.20.0.0/16 指向 B10.20.30.0/24 指向 C。现在有一个目的地址 10.20.30.15三条都能匹配按最长前缀选 /24 那条走 C。如果目的地址是 10.20.40.15前两条匹配选 /16 那条走 B。如果目的地址是 10.99.0.1只有第一条匹配走 A。这个逻辑没有任何模糊空间完全确定。但实际转发时还有几个变量会影响结果。一是策略路由管理员可以配置源地址是某网段、目的地址是某网段、端口是某端口的流量走特定下一跳优先级高于普通路由表。二是等价多路径如果两条路由前缀相同、开销相同流量会被分摊到两条路径上这时候抓包可能看到包从不同路径到达顺序被打乱。三是 NAT源地址转换会改变包头导致回程的路由决策跟去程不一致形成不对称路径。注意不对称路径不一定有问题但如果链路上有状态防火墙回程包可能被当成非法连接丢弃。表现就是能发出请求但收不到响应而且只在特定方向出现。4.3 ICMP 不只是 ping它是排障的信息源很多人对 ICMP 的理解就停在 ping其实 ICMP 有好几种类型每一种都携带了排障需要的信息。回显请求和回显应答是 ping 用的目的不可达分好几种代码网络不可达、主机不可达、端口不可达、需要分片但被禁止每一种都指向不同的问题超时消息是路由追踪的基础重定向消息告诉发送方下次可以直接发给另一个网关这个在复杂拓扑里会导致路径变得难以预测。我特别想说需要分片但被禁止这一类。它是路径 MTU 发现的核心反馈但也是最容易被拦的一类。很多安全策略默认丢弃所有 ICMP理由是防止探测结果把正常的 MTU 协商也一起掐死了。在这种环境里你必须手工把 MTU 调小到一个保守值比如 1400 或者 1300牺牲一点效率换连通性。还有一种情况是 ICMP 被限速。有些设备对 ICMP 做了速率限制每秒只回若干个。你用 ping 测试时看到丢包率很高就以为是链路质量差实际上是回应包被限速丢了。区分方法很简单看请求包和应答包的计数如果请求都发出去了、应答少了再配合 TCP 业务测试如果 TCP 大流量正常那基本就是 ICMP 限速的问题。5. 传输层TCP 和 UDP 的真实差异在哪传输层是开发者最常打交道的一层也是最容易以为自己懂的一层。TCP 和 UDP 的区别背出来就那几句TCP 可靠、面向连接、有流量控制UDP 不可靠、无连接、开销小。但真到调优和排障的时候这几句话一点用都没有你需要知道的是具体机制在什么条件下会失效。TCP 的可靠性建立在三个机制上序号、确认、重传。每个字节都有序号接收方通过确认号告诉发送方我已经收到了这个序号之前的所有数据。如果发送方在超时时间内没收到确认就重传。这个机制看起来天衣无缝但它有一个隐含前提超时时间要设得合理。设太短正常的高延迟链路会被误判为丢包触发不必要的重传反而加重拥塞设太长真丢包时恢复慢。现代 TCP 用的是自适应重传超时通过持续测量往返时间来动态调整。但即使这样在高延迟或者延迟抖动大的链路上重传超时依然容易误判。这时候更有效的是快速重传接收方收到乱序的包时立刻重复发送对最后一个有序字节的确认发送方连续收到三个重复确认就知道中间丢了包不用等超时直接重传。这个机制把恢复时间从一个超时周期缩短到三个往返效果显著。流量控制靠滑动窗口。接收方在确认报文里带上自己的接收窗口大小告诉发送方我还能接收这么多字节。发送方保证在途未确认的数据不超过这个窗口。窗口变成零时发送方停止发送定期发探测包询问窗口是否恢复。这个机制防止发送方把接收方淹没但也引入了一个经典问题如果窗口太小带宽就上不去。5.1 带宽时延积为什么你的窗口总是太小这是我认为传输层最值得算一遍的公式。带宽时延积等于带宽乘以往返时间单位换算成字节就是在途数据量的理论上限。如果接收窗口小于这个值链路就永远跑不满。算一遍链路带宽 100Mbps往返时间 50 毫秒。带宽换算成字节每秒是 100 除以 8等于 12.5 兆字节每秒。乘以 0.05 秒得到 0.625 兆字节也就是 625KB。这意味着什么意味着发送方必须有至少 625KB 的在途数据才能把这条 100Mbps 的链路填满。如果接收窗口只有 64KB那么实际吞吐上限就是 64KB 除以 0.05 秒等于 1.28 兆字节每秒也就是大约 10Mbps。一百兆的链路跑出了十兆的效果问题不在带宽在窗口。这个计算解释了很多带宽够但速度慢的困惑。跨地域的链路往返时间动辄几十毫秒甚至上百毫秒窗口不够大就必然跑不满。解决办法是启用窗口缩放选项把窗口上限从 64KB 提高到更大具体倍数在握手时协商。但要注意窗口缩放需要两端都支持而且中间如果有设备做 TCP 代理或者连接跟踪可能会把缩放选项吃掉。带宽往返时间需要的窗口64KB 窗口下的实际吞吐100Mbps10ms125KB约 51Mbps100Mbps50ms625KB约 10Mbps1000Mbps20ms2.5MB约 26Mbps1000Mbps100ms12.5MB约 5Mbps注意上表的实际吞吐是按 64KB 窗口除以往返时间算出来的理论上限实际还会受到拥塞控制、丢包率等因素影响通常更低。所以跨地域传输性能差先算一遍这个数比盲目调参数有用。5.2 拥塞控制从慢启动到快速恢复流量控制是接收方的事拥塞控制是网络的事。发送方维护一个拥塞窗口实际发送量取拥塞窗口和接收窗口的较小值。拥塞窗口的调整分几个阶段。慢启动阶段窗口从很小的值开始每收到一个确认就加一个最大报文段长度效果是指数增长每个往返翻一倍。名字叫慢其实是起步慢、增长快目的是快速探测链路容量。增长到一个阈值之后进入拥塞避免阶段改成每个往返加一个报文段线性增长。一旦检测到丢包就把阈值降到当前窗口的一半窗口重置重新开始。这里要区分两种丢包信号的处理方式。如果是超时重传说明情况比较严重窗口直接降到最小值重新慢启动。如果是三个重复确认触发的快速重传说明只是个别包丢了链路整体还行这时候用快速恢复窗口降到一半然后直接进入拥塞避免不用回到起点。这个区别很重要因为超时和快速重传反映的网络状况完全不同。实测中你会发现高丢包链路下 TCP 的吞吐会断崖式下跌因为每次丢包都把窗口砍半窗口长期在低位徘徊。这种链路上加大初始窗口、启用更激进的拥塞控制算法能改善但根本办法还是降低丢包率。5.3 握手、挥手和那些状态背后的含义三次握手的目的不只是建立连接更重要的是交换初始序号和协商参数。第一次客户端发同步报文带上自己的初始序号和选项第二次服务端回同步确认带上自己的初始序号和对客户端序号的确认第三次客户端回确认。为什么不能两次因为两次无法确认客户端的接收能力和服务端的发送能力同时正常而且历史连接的重复报文可能被误认为是新连接。三次是能够双向确认的最小次数。四次挥手是因为 TCP 是全双工的两个方向要分别关闭。主动关闭方发终止报文被动方先回确认此时主动方不再发数据但还能收数据这个状态叫半关闭。被动方把剩余数据发完之后再发自己的终止报文主动方回确认连接才算彻底关闭。主动方最后要等待一段时间才真正释放这个等待时间是两倍的最大报文生存时间目的是确保最后一个确认能到达对方以及让旧连接的重复报文在网络中消散。这个等待状态是很多端口耗尽问题的根源。高并发的短连接场景下大量连接停留在等待状态占着端口不放新连接建不起来。解决办法有几个一是用长连接替代短连接从根上减少连接数量二是调整系统参数允许重用处于特定状态的连接三是扩大可用端口范围。我倾向于第一种因为参数调整只是缓解症状。抓包看握手能发现很多问题。如果同步报文发出去了但没有回应可能是对端没监听、被防火墙拦了、或者路由不通。如果回应了但客户端没回第三个确认可能是客户端收到回应太晚已经放弃或者回应包的源地址不对。如果握手正常但第一个数据包就超时可能是 MTU 问题或者服务端处理慢。6. 排查实录分层速查表和踩过的坑真正干活的时候没人会按教材顺序一层层往下走你需要的是一个能在几分钟内缩小范围的清单。我把自己常用的顺序整理成表从最便宜的检查开始逐步往贵的方向推进。现象优先怀疑层第一步动作关键判据完全不通物理层看端口灯、看链路状态链路是否 Up时通时不通物理层/链路层看误码计数增长CRC 错误是否持续增长同网段不通链路层查 MAC 表、查 VLANMAC 是否学到跨网段不通网络层查网关、查路由表路由是否存在小包通大包不通网络层探测路径 MTU临界长度是多少能连上但速度慢传输层算带宽时延积窗口是否够大大量连接失败传输层看连接状态分布是否端口耗尽6.1 几个反复出现的典型坑第一个坑是双工不匹配。一端强制全双工另一端自适应自适应那端检测不到对方的协商信号退回到半双工。半双工下冲突增多表现是速率上不去、延迟抖动大、误码计数增长。这种问题在老旧设备混用的环境里特别常见解决办法是两端都设成自适应或者两端都强制成相同的模式和速率绝不能一边强制一边自适应。第二个坑是 MTU 黑洞。前面讲过原理这里说现象网页打不开但能 ping 通某些接口能调某些不能调文件小的时候能传大了就断。这类问题的迷惑性在于它是部分可用很容易被误判成应用 bug。我的经验是只要看到部分请求失败且失败的都是较大的请求立刻去验证 MTU。第三个坑是 TCP 窗口缩放被中间设备破坏。两端都启用了窗口缩放协商也成功了但中间有个设备做连接跟踪时没正确处理这个选项导致窗口被限制在 64KB。表现就是跨地域传输速度上不去本地测试完全正常。这种情况只能靠抓包看握手时的选项协商和后续的实际窗口值来确认。第四个坑是 ARP 表项老化导致的间歇中断。ARP 表项有生存时间到期会删除下次通信要重新解析。正常情况下重新解析很快不会有感知。但如果解析请求被丢弃或者回应慢就会出现几秒钟的中断。这种问题在高负载的网关上比较常见表现是每隔一段时间卡一下。缓解办法是适当延长表项老化时间或者配置静态表项但静态表项的维护成本高规模大了不现实。6.2 我个人总结的几条经验抓包永远是最后手段但不是最差手段。很多人觉得抓包重、麻烦喜欢先猜。我的做法是先看计数器计数器能解决的问题绝不抓包。端口统计里的错误计数、丢包计数、队列丢弃计数这几项能覆盖大部分物理层和链路层问题看一眼就知道要不要继续往下查。时间同步比你想的重要。多台设备同时抓包做对比时如果时钟不同步你根本对不齐时间线看到的现象全是矛盾。做联合排障之前先确认各设备的时钟偏差在可接受范围内这个前置动作能省掉后面大量扯皮。不要迷信网络没问题这句话。说这话的人通常只看了带宽利用率和 ping 延迟而这两项对很多问题是盲区。误码、分片、窗口、连接状态分布这些都不在常规监控里。你要问的不是网络通不通而是在这个具体场景下哪一层的哪个指标可能异常。改动之前先记录。调 MTU、调窗口、改路由改完出问题时你需要知道改之前是什么样。我见过太多次改完更慢了但不知道原来是多少的情况只能从头试。花三十秒把原配置存一份比事后猜半小时划算。分段验证比整体验证可靠。怀疑链路有问题就用两台设备直连测排除中间环节怀疑应用有问题就用最简单的客户端手工发请求排除框架干扰。每减少一个变量结论的可信度就高一分。这个思路不限于网络排障但网络这边尤其明显因为链路太长、环节太多。最后分享一个我常用来快速判断问题层次的小技巧拿同一个目标地址分别用 ICMP、TCP 小包、TCP 大包做三次探测。ICMP 能通说明网络层可达TCP 小包能建连说明传输层和端口没问题TCP 大包失败说明 MTU 或者链路质量有问题。三步下来一分钟能排除掉大半的可能性比翻日志快得多。这套方法我在不同规模的网络里都用过虽然粗糙但足够把方向定下来剩下的就是顺着方向深挖。