0. 写在前面:为什么你需要“神器”而非“常用命令
有时,诡异的卡顿像雾,贴着屏幕不散:延迟忽高忽低、丢包若隐若现,业务像被无形的手攥着喉咙。别急着把问题归咎于“网络黑洞”,也别一上来就全量重启。把系统当成乐器来调音:哪根弦松了,哪处共振了,靠证据说话。下面这套排查路径与操作清单,落地就能用;每一步都给出命令与模拟输出,尽量还原现场。
一、定位思路:把复杂问题拆成四个问句
• 这是端点的问题还是中间路径的问题?(主机栈/网卡 vs. 路由/对端)
• 是瞬时拥塞还是持续瓶颈?(尖峰 vs. 稳态)
• 是 L2/L3 的物理/MTU/丢包,还是 L4/L7 的重传/排队?
• 影响面在哪个范围?(同机房、跨区域、公网)
判断清晰,后面的动作就有了顺序。
二、十分钟“快检”小流程(不改配置,只观察)
1)测端到端延迟分解(连接、TLS、首包、总耗时)
$ curl -sS -o /dev/null -w "code=%{http_code} conn=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n" https://api.example.com/ping
code=200 conn=0.012s tls=0.034s ttfb=0.078s total=0.095s
解读:如果 conn
和 tls
很小,ttfb
突然变高,更多是服务端/上游处理慢;相反,如果 conn
偶发变大,像是网络路径在发脾气。
2)观察 TCP 视角的实时 RTT、重传、拥塞窗口
$ ss -ti '( dport = :443 or sport = :443 )' | head -n 8
ESTAB 0 0 10.0.0.5:52364 203.0.113.10:443
cubic wscale:7,7 rto:204 rtt:78.2/2.1 ato:40 mss:1448 cwnd:10 retrans:1/19
解读:rtt:78.2/2.1
表示均值/抖动;retrans:1/19
意味 19 个段中有 1 次重传——轻微可接受,持续升高要警惕。
3)端到端路径健康(MTR 同时看延迟与丢包)
$ mtr -ezbw -c 100 api.example.com
Start: 2025-08-10T10:30:00
HOST: app-01
1.|-- 10.0.0.1 0.2% 100 0.3 0.5 0.2 2.1
2.|-- 10.0.3.254 0.0% 100 0.7 0.9 0.5 3.0
3.|-- 172.16.1.1 5.0% 100 2.1 5.6 1.9 20.4
4.|-- 203.0.113.10 5.0% 100 6.9 12.2 5.7 42.7
解读:第 3、4 跳都有 5% 丢包,可能是第 3 跳开始拥塞或限速;若只有中间节点丢包但末端 0%,可能只是中间设备对 ICMP 限速,不必惊慌。
4)本机是否在丢包(驱动/队列/环形缓冲)
$ ip -s link show dev eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
RX: bytes packets errors dropped overrun ...
8.4G 9.2M 0 5321 0
TX: bytes packets errors dropped carrier ...
7.1G 8.1M 0 0 0
RX dropped
持续增长,多半是收包环溢出/软中断不及。
$ ethtool -S eth0 | egrep -i 'drop|err|rx_.*no|fifo' | head
rx_no_buffer: 4873
rx_missed_errors: 0
rx_fifo_errors: 0
5)核对 MTU / Path MTU 黑洞
$ tracepath -n api.example.com | head -n 3
1?: [LOCALHOST] pmtu 1500
1: 10.0.0.1
2: 10.0.3.254 pmtu 1500
$ ping -c3 -M do -s 1472 api.example.com
PING ... 1472(1500) bytes of data.
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
如果 1472 成功而更大失败,说明 PMTU 正常;如果连 1472 都不通且小包通,怀疑中间设备丢弃“不可分片”ICMP——典型 PMTUD 黑洞。
三、系统层面证据:把“感觉慢”变成“数字指纹”
1)丢包与重传的全局计数
$ nstat -az | egrep 'TcpRetransSegs|IpInDiscard|IpInDelivers|UdpInErrors'
TcpRetransSegs 321
IpInDiscard 57
UdpInErrors 0
$ sar -n DEV,EDEV 1 3
11:20:01 AM IFACE rxpck/s txpck/s rxerr/s txerr/s rxdrop/s txdrop/s
11:20:02 AM eth0 15234 13012 0.00 0.00 5.00 0.00
rxdrop/s
持续不为 0,就是主机侧接收丢包。
2)软中断与 ksoftirqd 压力
$ top -H -b -n1 | sed -n '1,15p'
%Cpu(s): 12.3 us, 7.8 sy, 0.0 ni, 60.0 id, 0.0 wa, 19.7 si, 0.2 st
si
(softirq)高企 + ksoftirqd/*
线程靠前,提示中断风暴/大流量抢占 CPU。
$ cat /proc/softirqs | sed -n '1,12p'
CPU0 CPU1
NET_RX: 1234567 345678
NET_TX: 234567 123456
3)队列、qdisc 与 bufferbloat 线索
$ tc qdisc show dev eth0
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap ...
pfifo_fast
在突发场景容易排队膨胀→高延迟。后面给出切换 fq_codel
的方法。
四、常见根因与修复动作(带“如何验证”)
以下调整尽量先在非生产验证,再按变更流程施行。涉及内核网络栈的修改,建议先单机灰度、再扩大范围。
A. 接收环/软中断处理不过来 → 调整网卡 ring / RPS / 中断亲和
1)查看并适度增大 ring buffer(硬件/驱动允许时):
$ ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096
Current hardware settings: RX: 512 TX: 512
$ sudo ethtool -G eth0 rx 2048 tx 1024
2)打散软中断到多核(RPS/RFS 示例):
# 为 eth0 的队列设置 RPS 掩码(示例掩码 0x3 -> 使用 CPU0/CPU1)
$ echo 3 | sudo tee /sys/class/net/eth0/queues/rx-0/rps_cpus
3)验证:sar -n EDEV 1
的 rxdrop/s
应下降,ss -ti
的 retrans
趋于稳定。
B. MTU/PMTUD 黑洞 → 统一 MTU 或在边界做 MSS Clamp
1)找出异常路径(大包不通):
$ ping -c3 -M do -s 1472 api.example.com # 1500 测试
$ ping -c3 -M do -s 8972 api-internal.example.com # 如果内部是 9000 jumbo
2)临时缓解(网关上钳制 MSS 到路径 MTU):
# iptables 版本
$ sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# nftables 版本(推荐新系统)
$ sudo nft add rule inet filter forward tcp flags syn tcp option maxseg size set clamp-to-pmtu
3)长期修复:统一子网 MTU(云上常见 1500/9001 混用),或打通 ICMP “需要分片但 DF 置位”的返回。
4)验证:tracepath
pmtu 稳定、业务大包传输不再超时。
C. Bufferbloat(排队膨胀)→ 切换到 FQ-CoDel / 启用 BBR
1)切换默认队列为 fq_codel
(减少排队延迟):
$ echo 'net.core.default_qdisc=fq_codel' | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p
$ tc qdisc replace dev eth0 root fq_codel
2)启用更友好的拥塞控制(BBR,内外网要兼容):
$ echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = cubic reno bbr
3)验证:长流下 ss -ti
的 rtt
抖动收敛、tc -s qdisc
中 drops
不再持续增长;端到端 curl -w
总时延下降。
D. CPU 上不来(软中断与用户态争抢) → 中断亲和/多队列/NUMA 绑核
1)将 NIC 队列中断绑定到不同 CPU,避免全集中在 CPU0:
$ grep eth0-TxRx /proc/interrupts
57: 123456 IR-PCI-MSI eth0-TxRx-0
58: 98765 IR-PCI-MSI eth0-TxRx-1
# 把中断 57 绑到 CPU0,58 绑到 CPU1
$ echo 1 | sudo tee /proc/irq/57/smp_affinity_list
$ echo 2 | sudo tee /proc/irq/58/smp_affinity_list
2)开启 RSS/多队列收发(硬件支持时):
$ ethtool -l eth0
Channel parameters for eth0:
Pre-set maximums: RX: 8 TX: 8
Current hardware settings: RX: 2 TX: 2
$ sudo ethtool -L eth0 combined 4
3)验证:/proc/interrupts
分布均衡,si%
降低,rxdrop/s
收敛。
E. 防火墙/ACL/限速导致 ICMP 或端口间歇丢包 → 用 TCP MTR 与计数器证据
1)当 ICMP 被限速时,用 TCP 探测:
$ mtr -ezbw -c 50 -T -P 443 api.example.com
2)检查本机防火墙计数器(哪个规则在吞噬包):
# iptables
$ sudo iptables -L -v -n | head -n 20
Chain INPUT ...
pkts bytes target prot opt in out source destination
# nftables
$ sudo nft list ruleset | sed -n '1,80p'
3)验证:放宽或修正规则后,curl -w
、mtr
的丢包恢复正常。
F. 服务器端处理慢被误判为“网络慢” → 从 TCP 层拆分时间
1)观察 RTT 正常但 ttfb
高,说明网络不是主因:
$ ss -ti state established '( dport = :443 )' | head -n 6
ESTAB ... rtt:8.1/1.2 retrans:0 ...
2)对服务端做“冷热点”确认:磁盘 IO、上游依赖、线程池。网络排除后,把精力放回应用。
G. UDP 抖动/丢包(实时音视频/日志投递) → 用 iperf3 的 UDP 模式
# 目标端
$ iperf3 -s
# 源端
$ iperf3 -u -b 200M -l 1200 -c 203.0.113.10 -t 30
[ 5] 0.00-30.00 sec 690 MBytes 193 Mbits/sec 1.2% 3.45 ms 4.12 ms 12.1 ms
抖动(jitter)与丢包率直观呈现;调低速率/分片长,观察阈值点。
五、应用一体化验证:别只看网络,要对业务负责
1)HTTP 探活与 95/99 分位延迟
$ for i in {1..50}; do curl -s -o /dev/null -w "%{time_total}\n" https://api.example.com/ping; done | awk '
{p[NR]=$1} END{
n=asort(p);
p95=p[int(0.95*n)]; p99=p[int(0.99*n)];
printf("p95=%.3fs p99=%.3fs\n", p95, p99)
}'
p95=0.112s p99=0.148s
2)TCP 连接失败率(应用可感知)
$ journalctl -u myapp -n 200 --no-pager | egrep -i 'ECONNRESET|ETIMEDOUT|EHOSTUNREACH' | wc -l
3
把“连接错误数/请求数”纳入监控,比肉眼追日志可靠。
六、常见“坑位图库”(你大概率会遇到)
• 云环境混用 MTU:VPC 内 1500,与跨 AZ/专线 9001,跨边界丢包。
• 容器与宿主 MTU 不一致:CNI 默认 1450,宿主 1500,外链 GRE/VXLAN 叠加——用
tracepath
查清楚。• 驱动 Bug/固件老旧:
dmesg | grep -i 'NETDEV WATCHDOG'
、link down/up
抖动;升级内核/驱动是最稳的解。• 队列默认 pfifo_fast:峰值时 RTT 爆炸;切
fq_codel
往往立竿见影。• ICMP 被彻底屏蔽:
ping
不通≠服务不通,谨记用mtr -T
与curl -w
双证据。• conntrack 被打满:连接瞬时飙升,
nf_conntrack_count
接近max
,丢包像退潮一样整片消失;调上限/调超时/分流是治本。
$ cat /proc/sys/net/netfilter/nf_conntrack_count
1048575
$ cat /proc/sys/net/netfilter/nf_conntrack_max
1048576
七、演练脚本(非侵入,只读采样)——一次跑完抓关键证据
仅采集,不更改系统;可在跳板机或业务机执行。请根据安全规范保存输出。
#!/usr/bin/env bash
# 名称:net-quickcheck.sh(只读体检)
set -euo pipefail
TARGET="${1:-api.example.com}"
PORT="${2:-443}"
COUNT="${3:-100}"
echo"=== curl timing (${TARGET}) ==="
curl -sS -o /dev/null -w "code=%{http_code} conn=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n""https://${TARGET}:${PORT}" || true
echo -e "\n=== TCP sockets RTT/retrans (sample) ==="
ss -ti "( dport = :${PORT} or sport = :${PORT} )" | sed -n '1,20p' || true
echo -e "\n=== mtr (${COUNT} cycles) ==="
command -v mtr >/dev/null && mtr -ezbw -c "${COUNT}" -T -P "${PORT}""${TARGET}" || echo"mtr not found"
echo -e "\n=== interface drops (ip -s link) ==="
ip -s link | sed -n '1,200p'
echo -e "\n=== NIC stats (ethtool -S) ==="
command -v ethtool >/dev/null && ethtool -S eth0 2>/dev/null | egrep -i 'drop|err|fifo|nobuf' || echo"ethtool or stats not available"
echo -e "\n=== stack counters (nstat) ==="
command -v nstat >/dev/null && nstat -az | egrep 'TcpRetransSegs|IpInDiscard|UdpInErrors' || echo"nstat not found"
echo -e "\n=== qdisc ==="
tc qdisc show dev eth0 || true
echo -e "\n=== PMTU / tracepath(5 hops) ==="
command -v tracepath >/dev/null && tracepath -n "${TARGET}" | sed -n '1,5p' || echo"tracepath not found"
echo -e "\n=== conntrack usage (if present) ==="
for f in /proc/sys/net/netfilter/nf_conntrack_{count,max}; do [[ -r "$f" ]] && echo"$f: $(cat $f)"; done
模拟运行输出节选:
=== curl timing (api.example.com) ===
code=200 conn=0.010s tls=0.031s ttfb=0.082s total=0.096s
=== TCP sockets RTT/retrans (sample) ===
ESTAB ... rtt:81.2/3.1 mss:1448 cwnd:10 retrans:2/47
=== interface drops ===
RX ... dropped 120 overrun 0
TX ... dropped 0 carrier 0
=== qdisc ===
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap ...
八、变更动作“口袋卡”(需要审批的改动,给出最小化命令)
建议:先一台机器灰度、收集指标、再推广。
• 切换队列调度器:
sudo tc qdisc replace dev eth0 root fq_codel
• 启用 BBR:
echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
• 调整 ring:
sudo ethtool -G eth0 rx 2048 tx 1024
• RPS 打散:
echo 3 | sudo tee /sys/class/net/eth0/queues/rx-0/rps_cpus
• MSS 钳制(PMTU 黑洞缓解):
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # 或 nft 同等规则
九、复盘与固化:把“偶发事故”变成“可预期的物理量”
• 监控层面加入:
rtt/ttfb
、TcpRetransSegs/s
、ip -s link dropped
、conntrack 使用率
、mtr 可视化
。• 发布变更时标注 MTU/队列算法/拥塞控制与版本。
• 每季度做一次“网络劣化演练”(
tc netem
注入延迟与丢包),验证应用的超时/重试策略是否健壮。
示例(仅在演练环境):
# 模拟 50ms 延迟和 1% 丢包
$ sudo tc qdisc add dev eth0 root netem delay 50ms loss 1%
# 还原
$ sudo tc qdisc del dev eth0 root
尾声
网络像一条看不见的河,水势有枯有涌。延迟与丢包不是神秘学,它们有迹可循,有数可证。把“快检”放在指尖,把“证据”刻进流程,把“修复”做成可回滚的变更。这样,当下次雾起时,你会更早看见河床的纹理,而不是被水声吓倒。
老杨时间
这里我先声明一下,日常生活中大家都叫我波哥,跟辈分没关系,主要是岁数大了.就一个代称而已.
我的00后小同事我喊都是带哥的.张哥,李哥的.
但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适.
比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“
这个氛围配这个称呼在互联网这行来讲就有点对不齐!
每次遇到这个情况我就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.我干了,你们随意!”
所以以后咱们改叫老杨,即市井又低调.还挺亲切,我觉得挺好.
运维X档案系列文章:
企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)
点击原文链接访问实时vps信息查询及小工具汇聚项目
老杨的关于AI的号