ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

网络与IO问题排查实战:从方法论到工具链的全流程指南

网络与IO问题排查实战:从方法论到工具链的全流程指南 写这一章的时候我特意把网络问题和IO问题放在一起写。干运维和开发这些年我发现大多数人应对这两类故障时最大的障碍不是不会用命令而是没有一个稳定的排查思路——一上来就抓包、一上来就重启结果问题复现了三次还是定位不到根因。其实网络问题的本质是数据在链路和协议栈里“卡住”了IO问题的本质是数据在设备和内核里“排队”了两者在排查方法论上高度同构。这一章就是把我平时处理线上问题的那套流程整理出来结合几个真实案例把网络与IO问题排查从“碰运气”变成“走流程”。适合运维工程师、后端开发、全栈同学以及正在啃网络和系统底层知识的嵌入式开发者参考。1. 先把排查思路捋清楚网络和IO问题背后的共性逻辑1.1 网络、IO、网络IO三个概念先别搞混很多人一听到“网络IO”就以为它是“网络”和“IO”之间二选一其实这是三个不同层次的东西。网络指的是设备与设备之间的数据通信核心载体是网卡、交换机、路由器、防火墙关注的是IP、端口、路由、协议栈。IO全称Input/Output更侧重单台设备内部的数据进出典型代表是磁盘读写、内存访问、进程间通信当然也包括嵌入式设备里的GPIO输入输出。而网络IO则是数据流经网卡和协议栈时的输入输出路径它既有网络层“从哪来到哪去”的空间特性也有IO层“怎么排队、缓冲区多大、有没有阻塞”的时间特性。我习惯打一个比方网络是快递从杭州发往北京的跨城运输要经过高速、收费站、中转站磁盘IO是仓库内部的装卸和上架讲究的是货架位置和搬运效率网络IO则是快递到站后从车上卸到传送带再分拣的过程哪个环节慢都会让整单延误。想清楚这个分层排查的时候就不会跑偏。比如网页打不开你在业务日志里翻了半天代码结果最后发现是网线水晶头氧化导致物理层丢包。这种尴尬我见过太多次了。1.2 一条百试百灵的排查路线环境、路径、配置、资源不管问题是“间歇性卡顿”还是“彻底连不上”我排查的顺序永远固定在这四个维度里打转。环境物理线路、光纤衰减、网线接头、供电、散热、设备机房温度。这个维度最容易被人忽略因为越基础的问题越显得“低级”可实操中翻车最多的恰恰在这里。路径数据从源到目的地经过哪些设备每一跳的延迟和丢包如何。这里牵扯到路由设计、链路质量、中间防火墙和负载均衡策略。配置系统参数、内核参数、应用超时时间、TCP keepalive、代理设置、NAT映射、安全组规则等。大多数“离奇”问题的根源都在配置上。资源带宽、CPU、内存、磁盘队列、文件句柄、网卡多队列、软中断分布。即使前面三项都没问题资源耗尽也会把服务拖垮。这条路线我用了很多年方法论其实不复杂关键是你每次排查都按这个顺序走一遍而不是凭感觉跳步。很多新手一上来直接抓包抓了几百MB也不知道在看什么就是因为跳过了环境和路径的检查缺一个“全局视角”。有了这套思路下面开始进入具体实战。先从最让人头疼的网络问题说起。2. 网络问题实战从“卡顿”到“连接被重置”的定位过程2.1 先分清四种网络症状延迟、丢包、断连、低吞吐网络问题的表象五花八门但归根到底可以归纳成四类。症状典型表现初步怀疑方向核心工具延迟高页面打开慢、接口响应慢链路距离、带宽拥塞、DNS解析慢、服务器负载高ping、curl -w、dig丢包视频卡顿、下载中断、语音断续物理线路、交换机丢包、防火墙策略、无线干扰ping -f、mtr、tcpdump看重传连接中断连接被重置、WebSocket掉线、SSH断开NAT超时、keepalive失效、防火墙重置、服务端主动断开ss、tcpdump抓FIN/RST、日志吞吐量低带宽跑不满、传输速度远低于预期TCP窗口限制、网卡协商速率异常、磁盘IO瓶颈iperf3、ethtool、ss -i一个很重要的心得先判断症状类型再决定用哪套工具。我曾经见过一个同事用ping测了一个小时延迟但问题其实是“带宽跑不满”方向从一开始就错了。ping测的是延迟和连通性它没法直接告诉你带宽上限是多少。2.2 网络排查四板斧ping、traceroute、ss、tcpdump这四组命令我几乎每天都在用熟练到肌肉记忆。但“会用”和“用对”是两回事。先说ping。它测的是ICMP回显能确认三层连通性和RTT。但要注意ICMP有时会骗人很多防火墙会丢弃ICMP报文导致ping不通但业务其实正常反过来有一些业务端口已经挂了ACL却放通了ICMPping全通但网页就是打不开。所以ping只能作为第一步不能作为最终结论。再说traceroute和它的加强版mtr。traceroute利用TTL逐跳超时的机制探测源到目的之间的路径和每一跳的延迟mtr会持续发送探测包并统计每一跳的丢包率定位中间哪个节点有问题非常直观。实际使用我推荐mtr多一点mtr -n -c 100 --report 10.0.0.1它会输出从本机到目标每一跳的丢包率、延迟均值。如果最后一跳丢包很严重但前面的跳都正常基本能判断是目标设备本身或回程路由的问题如果中间某一段例如运营商骨干网丢包大那就得考虑换个线路或者和服务商沟通了。ss命令是netstat的现代替代品用来查连接状态、端口监听、连接数分布ss -antpl | grep 8080这条命令能快速看到8080端口是否在监听、处于LISTEN状态的地址、已建立的连接数、以及大量TIME_WAIT或SYN_SENT堆积。出现大量SYN_SENT说明对方没响应大量TIME_WAIT可能是连接频繁建立关闭大量CLOSE_WAIT则是应用没有正常关闭连接。最后是tcpdump。这是底层抓包的王牌工具能看到TCP握手的SYN、SYN-ACK、ACK以及断连时的FIN、RST报文直接判断连接在哪一步失败tcpdump -i eth0 tcp port 8080 -nn -c 100抓包文件最好导出后用Wireshark看那里能自动统计重传、乱序、RST等指标效率高很多。我个人经验是“抓包要抓两端”只抓一端经常会漏掉真正触发问题的报文。比如客户端认为连接还活着但服务器早就发过RST这个RST只在客户端这边看不到。2.3 实战案例一WebSocket突然断开报stream disconnected before completion这是我在一个消息推送服务上真实踩过的坑。客户端报错信息是stream disconnected before completion: failed to send websocket request: io底层还能看到类似peer closed connection with的异常。第一次遇到这种报错直觉是服务端把连接关了但查了一圈服务端日志没有任何主动断连的记录。排查过程是这样的先看客户端和服务端的连接是否还存在。用ss命令看客户端的TCP连接发现连接其实早就消失了说明断连发生在更早的时间点只是客户端应用层没有感知等到下一次发消息时才发现连接已死。抓包。在客户端抓发送时的包看不到任何握手或RST因为连接自己没了发消息时系统直接返回错误。查服务端和中间链路。服务端日志显示一切正常没有崩溃没有超时断连记录。于是把怀疑对象转向NAT设备和防火墙。确认链路结构后问题明朗了。客户端处于内网经过NAT网关访问公网的服务端。NAT设备的连接表项是有空闲超时机制的标准NAT设备的空闲超时通常在60秒到300秒之间。客户端的心跳间隔设置成了5分钟一次超过NAT的空闲超时时间于是连接表项被回收后续数据包到了NAT设备后发现没有对应映射直接丢弃对两端来说连接就像“凭空消失”了。再往下查发现应用层其实配了keepalive但TCP keepalive的默认探测间隔是2小时net.ipv4.tcp_keepalive_time7200根本起不到保活作用。解决方案不复杂却涉及三个层面的配合应用层心跳间隔要小于NAT空闲超时时间的一半这是最直接的解法。把心跳改成30秒一次问题立刻消失。调小TCP keepalive探测间隔例如改成300秒sysctl -w net.ipv4.tcp_keepalive_time300 sysctl -w net.ipv4.tcp_keepalive_intvl30 sysctl -w net.ipv4.tcp_keepalive_probes3服务端也要检查是否有DisconnectTimeout之类的主动断开逻辑有些框架默认60秒没有任何IO就会断开WebSocket。这件事给我的印象很深。很多“连接被重置”的问题根本不是有人重置了你的连接而是连接在底层静默消失等应用层发现时只剩一个“空壳”。排查断连类问题永远要把NAT超时和keepalive放在前三位的怀疑清单里。2.4 实战案例二50G专线带宽跑不满问题到底出在哪这个案例关于“网速”的误解特别典型。两个机房之间有一条带宽为50Mbps的专线但两边同步数据时传输速度只有2-3MB/s怎么调都上不去最后业务方差点加钱扩容。我的排查路径先用iperf3直接测裸TCP带宽iperf3 -c 10.10.10.2 -t 30 -i 1结果能跑到40多Mbps说明链路本身没问题物理层和网络层都是健康的。通过。同时量RTT发现往返延迟在70ms左右。这个数字看起来不大但在高带宽链路上延迟和带宽是相乘的关系。计算带宽延迟积BDP。BDP 带宽 × RTT 50Mbps × 0.07s ≈ 437.5KB。这意味着要填满这条链路TCP的发送窗口和接收窗口至少要达到438KB左右否则数据在管道里永远装不满。用ss -i看实际窗口ss -i看到TCP的接收窗口和发送窗口都远小于BDP拥塞窗口也涨不上去确认就是窗口限制导致吞吐量天花板。解决思路是调内核网络缓冲区参数sysctl -w net.core.wmem_max16777216 sysctl -w net.core.rmem_max16777216 sysctl -w net.ipv4.tcp_wmem4096 65536 16777216 sysctl -w net.ipv4.tcp_rmem4096 87380 16777216调完后再用iperf3测吞吐立刻翻了几倍接近专线上限。现在很多Linux发行版默认开启了窗口缩放window scaling现代内核也会自动调节窗口但如果你遇到的是老内核、嵌入式系统或者中间经过了某些严格限制TCP选项的网络设备这个坑照样会跳出来。高带宽高延迟链路也就是常说的长肥网络跑不满大多数情况都是BDP没算过窗口不够导致的。以后再遇到“明明带宽很大但速度就是上不去”的案子先算一遍BDP别急着升级带宽。3. IO问题实战当系统突然变慢我的定位流程3.1 先搞清楚是“哪个IO”在拖后腿网络问题相对容易分类IO问题更隐蔽。因为用户感知到的现象往往是“系统变慢了”“数据库变慢了”“文件传输变慢了”而不是直接告诉你“磁盘IO出问题了”。我的经验是遇到“慢”先分三层磁盘IO、网络IO、应用层IO阻塞。磁盘IO问题通常表现为CPU的iowait高、应用卡在读写文件上。网络IO问题表现为网卡吞吐高、TCP重传多、连接堆积。应用层IO阻塞则是进程在等待锁、等待事件通知、等待下游返回数据典型的是Java程序线程池满、数据库连接池耗尽。区分方法不复杂。先用top看一眼wa和CPU占比再用iostat看磁盘再用sar看网络。这三个都是免费工具每一台Linux机器都有排查时务必按照“先看系统指标再看进程指标最后看应用指标”的顺序走。3.2 磁盘IO排查三件套iostat、iotop、sariostat是磁盘IO的第一入口用法iostat -x 1重点看这几个列指标含义正常范围参考异常提示什么%util设备忙碌时间百分比机械盘长期超过80%要警惕SSD和机械盘不一样有时%util高但延迟还是低awaitIO请求平均处理时间含排队机械盘10-20msSSD 1ms左右await很高说明IO在排队r_await / w_await读/写请求平均时间读写差异大时要关注写慢通常和缓存策略、RAID有关svctm设备实际服务时间多数场景不是关键指标明显升高说明硬件层面变慢了avgqu-sz平均队列长度正常应很小队列长说明IO堆积严重iotop用来找“元凶进程”iotop -o -d 2它会实时列出每个进程的磁盘读写速度带上-o只显示有IO活动的进程很快就能定位是哪个进程在疯狂刷盘。有一次线上数据库变慢iostat显示磁盘接近打满iotop一查罪魁祸首居然是一个日志清理脚本在凌晨扫描全盘。这个脚本以前数据量小不影响等数据量上来就成了定时炸弹。sar更适合看历史趋势sar -d 1它能记录整台服务器的历史IO数据特别是你发现问题后可以回看这个时间点前后IO是否出现了突变判断是突发问题还是逐渐恶化。3.3 实战案例三磁盘IO利用率100%数据库查询全卡住这个案例是我帮一个团队定位数据库变慢的完整过程。现象是MySQL实例慢查询暴涨前端接口超时QPS掉了一半。第一步用top看发现wa很高CPU空闲但系统都在等待IO完成基本可以确认瓶颈在磁盘。第二步用iostat -x 1确认%util长时间卡在100%await在100ms以上确实是磁盘饱和。第三步用iotop找进程意外发现不只mysqld在读写还有一个logrotate进程和一个备份脚本同时在跑。生产环境的MySQL一般压力就大加上这两个重量级IO选手同时进场磁盘直接被打满。解决方案是错峰和限制优先级备份脚本改到凌晨低峰期跑并用ionice限制IO优先级ionice -c 3 /path/to/backup.shlogrotate的时机和频率调整避免和备份重叠。给MySQL的redo log和数据文件所在磁盘单独划分防止被其他临时写入干扰。后来这个团队又遇到过一次磁盘性能下降但这次iostat显示%util不高await却很高最终定位到RAID卡缓存策略被切换成了直写模式导致写入性能断崖下跌。这两个案子结合起来看就明白磁盘IO的“慢”可以是资源竞争、调度策略、硬件状态、缓存策略等多方面的原因不能只看单一指标。顺手提一个容易忽略的点文件系统快满时IO性能会明显下滑。很多服务把日志和运行数据写在同一块磁盘磁盘使用率超过90%以后碎片增加、分配变慢感知上就是“系统逐渐变卡”。平时给磁盘留20%以上空余不只是为了容量更是为了性能。3.4 网络IO被忽视的两个关键指标重传和软中断很多人看网络只看流量大小带宽用了多少这种视角在排查网络IO问题时经常漏掉真相。用sar看网卡时除了rxkB/s和txkB/s更要看rxdrop、txdrop和错误包sar -n DEV 1如果rxdrop或txdrop不为0说明内核和驱动层面已经开始丢包了。接着用ethtool确认硬件统计ethtool -S eth0 | grep -i drop硬件统计里的dropped如果持续增长要么是网卡环形队列缓冲区不足要么是驱动bug。调整队列长度可以救急ethtool -G eth0 rx 4096 tx 4096另一个被忽视却很常见的是软中断打满单核。网络收包后中断会触发软中断处理如果机器把大量网卡中断都分配在同一个CPU上那个CPU会飙到100%而其他核闲着。这时流量没法进一步上去系统却显得非常卡。常见的解法是开启多队列RSS和分发软中断RPSethtool -L eth0 combined 4 echo 7 /sys/class/net/eth0/queues/rx-0/rps_cpus还有一类“网络IO慢”其实是TCP重传造成的。tcpdump抓包后在Wireshark里看到大量TCP Retransmission和Dup ACK说明链路存在真实丢包数据在不断重传吞吐自然上不去。这种情况下问题不在服务器调优而在链路质量用mtr去查中间路径就能找到端倪。网络IO问题的本质往往是“系统或链路某个薄弱点扛不住流量”排查时把吞吐、重传、丢包、CPU软中断四张图拼在一起看判断依据就扎实得多。4. IO约束与硬件层面嵌入式场景的排查联想4.1 嵌入式IO口排查从“io口输入”到“IO约束”聊完服务器端的IO再说说嵌入式场景。这个领域的IO问题和云端完全不同它是物理世界和芯片世界的交汇点典型症状不是“慢”而是“没反应”或者“乱跳”。先说最简单的单片机GPIO输入。很多人用STM32时把PF0配置成普通IO口用结果死活没有反应。排查方向可能不止代码问题还要看引脚复用Alternate Function。PF0/PF1这类引脚通常默认复用为外部晶振引脚如果你在初始化时没有禁用HSE并明确把它配置成GPIO模式电平信号根本到不了你的代码逻辑里。所以遇到“引脚没反应”可以先拿示波器点一下引脚看外部信号到底进来了没有再看寄存器配置是否生效。还有“IO约束”这个词在FPGA和PCB设计里指的是引脚分配和时序约束例如Vivado的XDC文件。如果你的FPGA版本和约束文件里的bank电压标准对不上例如外部供电是LVCMOS33但约束里写的是LVCMOS18信号质量就会变成一团乱麻表现为接口状态随机跳变。排查这类问题不能靠改代码要靠读时序报告、看引脚电压、量波形。工业相机通过IO触发拍照也是这个逻辑。相机上的Line0/Line1可以作为硬件触发输入外接光电开关或PLC信号配置成“硬件触发”模式后信号一到就开始采图。接线要检查共地、电压范围和线缆屏蔽触发没反应时先确认信号电平到了引脚再确配置寄存器。硬件IO和服务器IO的排查思维其实一致先确认物理信号是否到达再看配置最后看软件逻辑。倒过来查永远事倍功半。4.2 排查前的重要一步先把网络拓扑图画清楚网络拓扑图在多设备环境下几乎是命脉。没有拓扑图你连“数据该走哪条路”都不知道排查根本无从谈起。我见过两台电脑用UDP调试助手通信一台发送另一台就是收不到。一追查两台机器分别在两个不同的VLAN交换机之间没有三层路由UDP广播包根本无法跨越VLAN边界。这种情况如果手边有一张标注了VLAN、IP段、交换机互连方式的拓扑图十分钟就能定位到“广播域隔离”这个问题而不是在应用配置里来回折腾。画拓扑不追求专业软件。draw.io、Visio、甚至手画在纸上都可以关键是标注清楚这些信息设备名称、IP、子网掩码、网关交换机端口、VLAN划分防火墙、负载均衡、NAT设备的位置物理链路类型光纤、网线、无线和速率排查时面对一张准确的拓扑你可以快速判断数据路径上有哪些设备可能插手、哪些策略可能生效、哪些节点可能成为瓶颈。没有拓扑图的排查就像没有地图的导航全凭运气。5. 常见问题速查表与避坑经验5.1 一张速查表覆盖高频问题把最近两三年遇到的高频问题整理成了一张速查表后面新团队来问问题我都是先让他们对着这张表自查一轮能过滤掉一半以上的“伪故障”。症状可能原因核心命令 / 手段网页打不开但ping通DNS解析、应用层故障、防火墙拦截curl -v、nslookup、ss -antpping不通但业务正常防火墙丢弃ICMP换端口测试、curl验证业务TCP连接一直建立不了端口未监听、防火墙丢弃SYN、半连接队列满ss -antl、telnet ip port、tcpdump看SYN连接空闲后断开NAT超时、keepalive没生效调整心跳为NAT超时一半、设tcp_keepalive连接频繁出现大量TIME_WAIT短连接太多ss -s统计、调高本地端口范围、开启reuse有线网络卡顿网线老化、交换机端口协商异常ethtool eth0查速率、ip -s link查错误包WebSocket连接被重置服务端主动断开、NAT超时、代理策略抓包看RST来源、查DisconnectTimeout高带宽链路跑不满TCP窗口限制、BDP计算不足iperf3测带宽、ss -i查窗口、调内核参数磁盘IO打满大量读写、备份脚本、RAID缓存策略iostat -x、iotop、ionice、查RAID策略数据库突然卡顿磁盘等待高、锁等待、连接池耗尽top查wa、iostat、慢查询日志、show processlist网卡吞吐上不去中断不均、单核软中断打满sar -n DEV、ethtool -L开启多队列、RPS配置多机UDP通信收不到数据VLAN隔离、广播域限制、防火墙查拓扑图、抓包、检查路由和ACL5.2 我踩过的几个大坑希望你绕开第一个坑是ICMP误判。有一次客户报“网络不通”ping却全通后来发现是业务端口被安全策略封掉ping用的是ICMP完全没有被拦。我后来给自己定了个规矩任何“通不通”的问题必须同时验证TCP端口和业务协议不能只看ping。第二个坑是只抓一端包。排查一个RST重置问题时在客户端抓了半天什么都没看到后来在服务端一抓发现连接其实早就被服务端重置了。抓包要抓两端尤其是有中间网络设备的时候两端的报文对不上正是定位问题的关键线索。第三个坑是修改内核参数不留记录。调了一堆网络参数问题也确实解决了但一个月后性能反而异常回查发现是另一个同事“优化”了同一个参数。所有线上变更都要留记录能上配置管理就上配置管理至少也要在变更前备份原值。第四个坑是忽略时间同步。服务器时间漂移几分钟排查日志时两端时间对不上白费半天功夫。NTP同步在排障场景里不是锦上添花而是基础前提。第五个坑是忘记看历史基线。没有基线就无法判定“异常”。我第一次遇到数据库IO问题时iostat的await显示80ms还觉得“好像还行”直到对比了三天前的数据才发现平时只有10ms出头。监控系统不一定要很复杂但一定要能回溯。还有一个和“第6章”这个章节定位相关的体会。排查这些网络与IO问题的过程中你会逐渐发现真正难的不是某个命令有多熟练而是建立一套“先分类、再分层、后归因”的思维方式。每次排障都是一次对系统全貌的重新理解排查的积累会反哺你对整个技术栈的掌控力。这一章讲的是方法但方法最终要变成你面对新问题时的第一反应。养成记录基线、保存变更、双端抓包这些习惯比记住一百条命令更有价值。
返回列表