全栈工程师网络排查全攻略:从连通性到应用层的命令手册
干这行久了你会发现全栈工程师最常被卡住的不是业务逻辑而是网络问题。服务明明在跑、代码看起来也没问题可请求就是不通要么ECONNREFUSED要么一直转圈最后超时要么只在生产环境复现、本地怎么都复现不出来。这类问题报错信息往往极少但可能的原因少说有几十种。我写代码这些年前后端、部署、上线都碰过真正让我下定决心整理一套网络排查命令手册的是几次被这种看不见的故障折磨到凌晨的经历。这篇内容不是教科书式的命令清单而是我个人在实际项目里反复用到的排查套路按从连通性到应用层的顺序展开适合全栈工程师随手翻查也适合刚接手前后端联调、上线部署的开发者建立基本的排查思路。1. 网络排查是全栈工程师的必修课但它不是从Ping开始的1.1 一次让我重新认识通不通的事故先说一件对我影响很大的事。有一年负责的一个线上服务突然大面积超时登录、下单接口全都变慢页面能打开但所有涉及后端请求的操作都在转圈。我当时的第一反应是查应用日志、查数据库慢查询结果后端日志显示一切正常数据库负载也不高。我又怀疑是代码发布引起的回退问题但版本回滚后故障依然存在。折腾了一个多小时最后才发现是机房物理链路出现间歇性丢包交换机上某个端口的光模块不稳定。这次事故给我最深的教训是代码和服务的健康状态是一回事网络链路的真实质量是另一回事两者没有必然联系。全栈工程师排查网络问题时如果一上来就扎进应用日志很容易在错误的方向上消耗大量时间。也是从那次之后我开始有意识地建立一套固定的排查顺序先判断链路是否通、再判断解析是否对、然后看端口和连接状态、接着看应用层交互细节、最后再回到代码层面。这个顺序不是随便排的是因为越底层的因素越容易一票否决上层的问题。物理链路不稳定应用层代码写得再好也白搭DNS解析错了服务进程再健康也访问不到。先把底层因素排除干净上层的分析才有意义。1.2 分层排查你的命令到底在看哪一层很多刚转全栈的朋友对网络排查这个概念很模糊觉得无非就是ping一下、通就继续、不通就重试。实际上一条请求从浏览器或客户端发出到最终被服务端处理中间要经过好几层每一层有自己的协议和故障类型也有对应的排查工具。我习惯把这套链路简化成四层来看物理链路层关心的是网卡、网线、交换机端口是否正常网络层关心的是IP能不能路由到目标地址典型工具是ping和traceroute传输层关心的是TCP/UDP端口是否可达、连接状态是否健康典型工具是telnet、nc、ss应用层关心的则是HTTP请求和响应本身是否符合预期典型工具是curl和tcpdump。当你脑子里有这条分层的线拿到一个接口不通的问题时就不会盲目试错而是能根据报错特征快速判断应该从哪一层入手。这里面有个很常见的误区很多人习惯ping通了就认为链路没问题其实ping只验证了ICMP协议和网络层可达性它既不验证端口也不验证应用层服务。反过来有些云服务器出于安全策略会屏蔽ICMP报文导致ping不通但业务端口实际是正常的。所以分层思维的第一课就是每个命令行工具只看一个层面cross-check交叉验证才是关键。2. 连通性诊断先回答通不通再回答通到哪2.1 Ping和它的迷惑性别让ICMP骗了你Ping大概是全栈工程师最早上手的网络命令它发送ICMP Echo Request报文并等待Echo Reply用来判断目标主机是否可达、往返延迟大概是多少。以Linux环境为例我常用的参数有这几个-c 4发送4个包后停止-i 0.2把发包间隔从默认的1秒缩短到0.2秒适合快速观察丢包-W 1每个包等待响应的超时时间设为1秒-s 1400设置包体大小适合顺带测一下大包会不会导致分片或丢包实际排查的时候我更建议这样执行ping -c 20 -i 0.2 -W 1 目标IP连续发20个包看丢包率和延迟分布。如果丢包率稳定为0、延迟也稳定说明网络层基本健康如果出现丢包或者延迟剧烈抖动那物理链路或者某个中间节点大概率有问题。但这里必须强调ping返回正常只代表网络层可达不代表TCP端口通更不代表服务进程活着。很多时候服务进程挂掉或者防火墙丢弃了对应端口的数据包ping依然能通。所以我通常把ping当作第一道快速筛查而不是最终结论。另一个容易踩的坑是ping通了但业务还是卡。这种情况通常不是连通性问题而是路径上某个高延迟节点或者中间设备做了限速。ping的通达性和时延只反映ICMP报文的表现真实业务流量走的是TCP/UDP路径可能相同但受拥塞控制、带宽限制的影响完全不同。2.2 Telnet、Nc与端口连通性从通到哪到通了没要验证某个TCP端口是否可达我常用的工具是两个telnet和ncnetcat。telnet的用法很简单telnet 192.168.1.10 3306能进入协议交互界面说明端口通如果提示Connection refused说明端口没监听或者服务没起如果一直卡住不动直到超时则往往说明中间有防火墙丢弃了数据包。不过telnet在部分发行版里默认不安装而且它只能验证TCP端口无法控制更多细节所以更灵活的是ncnc -zv -w 5 192.168.1.10 3306-z表示只扫描端口不发送数据-v输出详细过程-w 5设定超时5秒。nc还有一个优势是可以指定端口范围nc -zv -w 2 192.168.1.10 3306 8000 8080如果你要一口气确认多个端口这个用法非常省事。在Windows的PowerShell环境里我经常用另一个等价命令Test-NetConnection 192.168.1.10 -Port 3306它会直接输出TcpTestSucceeded字段是True还是False。这些命令解决的是同一个核心问题TCP握手能不能建立起来。如果能建立链路和防火墙基本没问题如果建立不了再结合报错类型去判断是服务没监听、防火墙丢弃、还是网络根本不可达。我见过很多前端同事在联调时说后端接口挂了结果我用nc一测端口通着只是服务响应很慢这完全是两类问题。2.3 Traceroute与MTR看数据包在哪一跳消失当ping显示丢包或者延迟很高时下一步就该定位丢在哪一段路上了。这里的主角是traceroute它通过递增TTL生存时间来迫使路径上的每一跳路由器返回ICMP超时报文从而把从本机到目标地址的完整路径勾勒出来。traceroute -n -T -p 80 www.example.com-n不做反向域名解析速度快很多-T表示用TCP SYN报文探测-p指定目标端口。这么做的好处是很多路由器会丢弃ICMP报文但TCP报文相对更容易通过能得到更真实的路径信息。traceroute输出的每一行是一跳依次是序号、IP地址、探测耗时。如果某一行出现三个星号说明这一跳没有返回报文可能是设备屏蔽了探测也可能是真的丢包需要结合前后几跳的表现来判断。不过traceroute是逐跳静态展示对于偶发性丢包作用有限。我更推荐用mtr它相当于traceroute和ping的结合体会持续发送探测包并统计每一跳的丢包率和延迟mtr -rwc 100 -T -P 443 www.example.com-r表示以report模式输出-w使用宽格式-c 100发100个包后结束。关键要看的是每一跳的Loss%列。如果只有某个中间节点丢包严重而最终目标节点丢包为0那通常说明该节点只是对ICMP限速不影响实际业务如果目标节点本身丢包明显那链路质量问题就基本坐实了。我在实际项目中用mtr定位过几次跨运营商访问卡顿的问题最后都落在了某一跳的骨干网节点高延迟上。这类问题单靠应用层日志根本发现不了不走到这一层你永远不知道时间消耗在哪。3. DNS排查很多诡异问题最后都藏在这里3.1 dig与nslookup查明白解析到了哪里如果说连通性排查关注的是路通不通那DNS排查关注的就是门牌号对不对。全栈工程师最容易遇到的场景是部署了新服务更新了DNS解析记录但线上访问依然指向旧地址或者同一个域名在不同的网络环境下解析出完全不同的IP。排查DNS的头号工具是dig它的信息量远超nslookup。最基础的用法dig www.example.com输出里重点看QUESTION SECTION查询的域名和类型、ANSWER SECTION最终解析结果、SERVER实际响应的DNS服务器地址和Query time解析耗时。如果要快速拿到结果可以加short参数dig www.example.com short但我在排查问题时很少直接short因为丢掉了TTL信息。TTL决定了这条记录可以被缓存多久很多DNS不生效问题都跟TTL设置有关。dig还支持指定DNS服务器这一点在排查为什么我这里是这个IP、别人那里是另一个IP时特别有用dig 223.5.5.5 www.example.com dig 8.8.8.8 www.example.com对比两个公共DNS的解析结果可以快速判断问题是出在权威DNS配置不一致还是本地递归DNS缓存了旧记录。如果两条命令返回的IP不一样那就是DNS配置层面的问题要在域名服务商的管理后台检查解析记录。另外dig的trace参数可以完整展示从根域名服务器到权威服务器的整个解析链路dig www.example.com trace这个功能在排查某个域名在本地解析正常、在外部解析不正常的场景下非常有效能看到每一级返回的权威记录是否一致。3.2 hosts、解析缓存与解析顺序的坑DNS问题里最隐蔽的一类是系统根本没走网络上的DNS。以Linux为例域名解析的查询顺序由/etc/nsswitch.conf文件决定默认配置一般是hosts: files dns其中files就表示先查/etc/hosts文件dns表示文件里没有命中再走网络DNS。所以当你在/etc/hosts里写了一条映射即使网络上的DNS记录已经更新系统也仍然会优先使用hosts里的配置。排查为什么解析没生效时第一件事就是确认这个文件里有没有遗留的旧记录。另一个更常见的坑是操作系统或本地服务引入的DNS缓存。在启用systemd-resolved的Linux发行版上普通命令比如getent hosts、curl可能走的是缓存到本机的127.0.0.53解析入口即使网络DNS已经更新系统解析结果短时间内也不会变。手动清缓存可以这样操作resolvectl flush-caches如果机器上装了nscd还有一份独立缓存清法不同nscd -i hosts而Windows环境的清缓存命令大家应该很熟了ipconfig /flushdns我遇到过一个很折腾的案例运维改了DNS的A记录指向新IP但测试机访问域名还是跳到老IP。用dig查公共DNS结果是对的查本地默认DNS结果也是对的。后来才发现是这台机器上的/etc/hosts里写了一条老IP的映射压过了所有网络解析。这类问题只要记得查hosts文件三秒钟就能定位但思维惯性会让很多人先怀疑DNS配置本身白折腾半天。4. 端口、连接状态与占用进程服务起没起来数据说了算4.1 ss还是netstat选型与高频用法过去我们习惯用netstat看端口和连接但现在的Linux发行版里我强烈建议优先用ss它是iproute2工具包的一部分性能更好、信息更准。特别是服务器上连接数上万时netstat会因为读取/proc/net/tcp而变得极慢ss则几乎不受影响。查看监听中的TCP端口和对应进程一行命令即可ss -lntp各字段拆开看State表示连接状态Recv-Q和Send-Q是接收和发送队列大小Local Address:Port是本机监听地址和端口Peer Address:Port是对端地址Process是占用该端口的进程。Local Address显示为0.0.0.0表示监听所有IPv4地址显示为[::]表示监听所有IPv6地址。如果只想看当前所有已建立的连接可以用ss -tn state established想按端口号反过来找进程用ss -lntp | grep 8080ss还有一个很实用的汇总参数ss -s它直接输出当前系统的TCP/UDP连接数量汇总以及各状态established、syn_recv、time_wait等的数量分布。这个命令在服务刚上线、想看连接压力时非常直观。4.2 连接状态TIME_WAIT与CLOSE_WAIT的缠斗全栈工程师在排查线上问题时最常盯着看的两个连接状态是TIME_WAIT和CLOSE_WAIT。TIME_WAIT出现在主动关闭连接的一方表示四次挥手的最后一个ACK已经发出等待足够时间以确保对端收到。大量TIME_WAIT看起来吓人但实际上是被动方或中间设备确认连接清理的必备过程并不直接代表问题。真正需要警惕的是CLOSE_WAIT它表示对端已经关闭连接但本地进程还没调用close()来关闭自己的这一侧。CLOSE_WAIT持续堆积几乎一定意味着应用代码有bug比如使用HTTP连接池没有正确释放连接或者处理异常时漏掉了finally块。排查CLOSE_WAIT堆积可以先看数量ss -s | grep -i close然后定位这些连接的对端和进程ss -tnp state close-wait | head -20看到大量相同对端IP和端口时就可以顺藤摸瓜找到对应的业务模块了。我自己处理过一次类似问题某个内网服务用Apache HttpClient调用另一个服务连接池配置了最大连接数却没配合适的空闲回收策略导致CLOSE_WAIT不断累积最后端口被耗尽。这类问题改网络参数是没有用的最终还是要回到代码层修复。4.3 lsof与fuser端口被占用的快速定位开发中最场景化的问题是端口被占用。Spring Boot项目默认8080Node项目默认3000经常出现同一个开发机上加多个服务然后启动时报端口冲突。查看某个端口被哪个进程占用用lsoflsof -i:8080输出里有COMMAND进程名、PID进程ID、FD、TYPE、DEVICE等字段。用这个PID就能进一步确认是不是自己之前起的残留进程。如果想直接杀掉占用端口的进程fuser更干脆fuser -v 8080/tcp fuser -k 8080/tcp-v先显示占用进程的信息-k直接发送SIGKILL。这里提醒一句kill之前最好确认一下进程身份尤其是服务器上别把别人正在用的服务误杀了。我在本地经常用fuser清理残留进程但在生产环境一定先ps查一下确认是预期中的进程再动手。另一个我能分享的经验是排查端口问题时不要只盯一个端口本身。有些服务监听在正常端口但依赖的Redis、MySQL端口被占用或连不上表现依然是服务无法启动。所以当监听端口看起来正常但服务依然报错时顺着进程的连接列表查一遍它依赖的下游端口往往比反复重启服务更有效。5. HTTP接口排查从curl到tcpdump的完整链路5.1 curl的调试参数把时间消耗拆到毫秒级当连通性、DNS、端口都排查完确认链路是通的接下来就该聚焦应用层了。curl是这里绝对的主力工具但很多人只会用curl -I或者curl URL其实它对排障最有价值的是-v参数和-w参数。-vverbose会输出整个请求的交互细节包括DNS解析阶段、TCP连接建立、TLS握手、发送的请求头、接收的响应头。示例curl -v https://api.example.com/v1/health通过这段输出你可以看到解析到哪个IP、连接是否成功、TLS证书链是否正常、请求是否被重定向。很多时候接口返回的数据不对但响应头里藏着302跳转、Set-Cookie、缓存标记这些信息肉眼快速扫一遍-v输出就能找到线索。而-w参数能做的更绝它可以把一次请求的各阶段耗时变量打印出来。我通常自己定义一个输出格式把最关心的几个时间点拆开看curl -o /dev/null -s -w DNS解析: %{time_namelookup}s\nTCP连接: %{time_connect}s\nTLS握手: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总耗时: %{time_total}s\n https://api.example.com/v1/health这几个时间量分别代表什么我用一个例子说明time_namelookupDNS解析耗时。如果这个数值很高说明本地DNS服务器或者递归查询链路有问题。time_connectTCP三次握手完成的时间从发起握手的SYN到收到SYN-ACK。如果time_connect减去time_namelookup很大说明网络链路延迟高或握手被中间节点干扰。time_appconnectTLS握手完成的时间。如果这里异常增大要考虑证书链过长、服务器CPU性能不足导致加解密慢。time_starttransfer从请求发出到收到响应首字节的时间。它减去time_appconnect基本就是服务端处理请求的真实耗时。把它们拆开看能直接区分问题在网络还是问题在服务避免争论半天是不是服务器慢却拿不出证据。5.2 tcpdump抓包三次握手和重传的真相当curl的量级拆解还不能满足需求比如怀疑TCP层有重传、丢包、连接被重置时就该请出tcpdump了。它能把网卡上经过的报文按过滤条件抓下来是定位“玄学型超时”的王牌工具。常见的抓包姿势tcpdump -i any -nn -s0 host 192.168.1.100 and tcp port 8080 -w /tmp/debug.pcap-i any表示抓所有网卡-nn不解析域名和端口名-s0抓完整报文host和tcp port是过滤条件-w把原始包写到文件里。抓完之后本地有Wireshark就打开分析没有就用tcpdump直接读取并简单过滤tcpdump -nn -r /tmp/debug.pcap | head -30在抓包结果里我最关注两类现象第一类是握手的流。一个正常的TCP建立过程会依次出现SSYN、S.SYN-ACK、.ACK三行。如果只有S没有后面两行说明对端压根没收到或没回应SYN要回到连通性和端口层面查如果看到了重传[TCP Retransmission]说明中间有报文丢失物理链路或中间设备嫌疑最大。第二类是RST包。RST表示连接被某方强制重置报文里带R标志。它出现的常见原因包括服务端进程崩溃、防火墙主动切断、端口根本没监听。如果抓包看到请求发过去立刻被RST那基本可以排除网络链路问题回到应用和防火墙层面继续查。我处理过一个小程序接口偶发超时的casecurl测试时大部分正常偶尔一次要等好几秒。事后抓包发现是TCP快速重传大量出现底层的丢包率其实不高但因为触发拥塞控制整体延迟被放大。这类问题如果不抓包单看应用日志永远是无异常容易被判定为客户端网络环境问题最后白耗很长时间。6. 带宽、网卡与有线网络卡顿全栈工程师也要会查物理层6.1 ethtool与mii-tool看网卡协商状态全栈工程师很多时候也在本地开发网卡物理状态对开发体验的影响比想象中大得多。特别是现在的笔记本和台式机普遍是千兆网卡一旦网线质量不行或者水晶头接触不良链路会自动降级到百兆甚至十兆协商。这种降级平时下载文件、看视频可能感觉不明显但在拉大仓库、跑前端构建、传输镜像的时候就非常痛苦。检查网卡协商状态最直接的是ethtoolethtool eth0关键看两行Speed当前协商速率正常千兆网卡应该显示1000Mb/s如果看到100Mb/s说明链路有降级。Link detectedyes代表物理链路是通的no代表网线没插好或者对端设备断电。除了速率还可看网卡统计信息里的错误计数ethtool -S eth0 | grep -i error重点关注rx_crc_errors、rx_errors、rx_dropped。CRC错误代表数据帧在传输过程中校验失败通常是线缆质量差、接头氧化、电磁干扰导致的。如果这些数字在不断增长物理层基本可以确认有问题。有些老系统没有ethtool可以用mii-tool应急mii-tool eth0它的输出会更直白地显示negotiated link speed。6.2 有线网络卡顿的常见原因与排查思路结合最近大家讨论比较多的有线网络卡顿问题我简单梳理一个排查顺序供全栈开发者在本地办公环境遇到网络不稳时参考。第一步是确认速度。用ethtool看协商速率如果出现“100Mb/s Full”这样的输出先把目标定在恢复千兆上因为从千兆降级到百兆本地局域网内大文件传输的速率上限直接砍掉九成。第二步是检查错误计数。连续跑几分钟流媒体或者大文件拷贝再执行ethtool -S对比rx_crc_errors和rx_errors的增长幅度。只要在增长基本就是物理链路问题。第三步是换线验证。把问题线路换成一根确认没有损坏的成品网线再重复前两步。如果协商速率恢复且错误计数停止增长故障源就是网线或者水晶头。如果换了线依旧就要继续检查网口、交换机端口、甚至网卡驱动。这个排查链路看起来不起眼但非常实用。我在办公室遇到过很多次网络很慢的反馈排查到最后都是网线问题而不是公司网络出口或者服务器的问题。全栈工程师如果自己就搞不定本地网络在远程协作崩掉的时候会很被动。6.3 iperf3用真实带宽数据说话除了网卡协商速率实际能跑出多少带宽是另一个维度的指标。iperf3是我用来做端到端带宽测试的工具。服务端在接收端启动iperf3 -s客户端在发送端执行iperf3 -c 192.168.1.100 -t 10 -P 4-t 10表示测试10秒-P 4表示用4个并发流。输出会给出每一条流的传输速率和总和。如果想测反方向下行加-R参数iperf3 -c 192.168.1.100 -t 10 -P 4 -R在测试本地局域网时如果结果是900Mbps以上说明链路健康。如果只有100Mbps左右基本就佐证了网卡协商降级的问题。这个工具的好处是做了一个端到端的真实传输测试排除了单点判断的误差。我还遇到过一种情况网卡协商显示千兆但iperf3测试速度只有两三百Mbps。后来排查发现是USB转网卡的适配器发热降速。这类软硬件结合的问题单看ethtool是看不出来的必须有实际的带宽测试结果才能锁定。所以我的建议是只要排查网络性能就把ethtool和iperf3配合起来用一个管协商状态一个管实际吞吐。7. 一次完整排障实录从接口偶发超时到网线水晶头7.1 现象与初步假设最后用一个实际排障案例把这些命令串成一条完整的链路。某次开发联调阶段前端同事反馈调用后端本地接口时偶发超时有时候几十个请求里有一个会卡四五秒重试一次又能成功。后端进程日志没有任何异常数据库查询也很快。当时我们下意识怀疑是前端网络问题被前端同事一句我访问其他服务都正常怼了回来。既然应用层日志看不出问题我决定按之前说的顺序从底层往上层过一遍。先确认连通性无异常DNS也没有特殊配置端口正常监听于是把重心放在链路质量和应用层交互细节上。7.2 逐层执行的具体命令和结果第一步用curl拆时间。连续执行了二十次请求观察到time_connect从正常的1毫秒左右偶尔跳到600毫秒甚至出现time_starttransfer整体飘到3000毫秒的情况。这说明问题大概率发生在TCP连接建立阶段或更底层而不是服务端业务处理。第二步用ping连续发包。命令是ping -c 100 -i 0.2 192.168.1.11结果显示丢包率约2%并且个别延迟到了200ms以上。局域网内出现这个数据基本可以确认链路是真的有问题不是错觉。第三步用mtr定位路径。因为目标就在同一个网段路径只有一跳mtr显示第一跳就出现了丢包和延迟抖动说明故障点在本机到交换机这一段。第四步回到物理层检查。用ethtool查看本机网卡发现Speed显示为100Mb/s而正确值应该是1000Mb/s。再执行ethtool -Srx_crc_errors的数值在持续增长。到这一步问题范围已经收敛到网线或端口连接了。7.3 根因修复与习惯养成最终排查出来是网线水晶头接触不良重新压接水晶头后协商速率恢复千兆ping丢包归零curl的time_connect也稳定在1毫秒左右接口偶发超时消失。整个过程大概半小时而最初我们几个人在应用日志和代码层面反复排查的时间远远超过这个数字。回头复盘这件事让我养成了一个习惯任何偶发不稳定的网络问题我都默认从物理链路和TCP层开始验证而不是从应用日志开始猜。因为应用层能看出来的问题通常已经被日志记录得比较明确了反而是这种底层的间歇性抖动最容易伪装成服务不稳定或代码有bug。对于全栈工程师来说掌握网络排查命令不是要成为网工而是为了在前后端联调、部署上线、线上问题追查时能用最短的时间把问题边界画清楚。边界画清楚了该查代码的查代码该报运维的报运维也才能做到用数据说服对方而不是靠争论和感觉。