Linux 服务器网络延迟高的排查思路
网络延迟(latency)升高是服务器最常见、最难一眼定位的性能问题之一。它可能源于本地内核栈处理慢、网络路径某一段拥塞、对端慢、DNS 解析、TCP 协议行为 或 硬件/虚拟化层 的多种因素叠加。
以下是目前最实用、可重复的分层排查框架,从最快验证到深度剖析,适合物理机、云主机(AWS/GCP/Azure/阿里云/腾讯云等)、容器宿主机场景。
第一步:明确延迟发生在哪一段
最核心问题:延迟是客户端 → 服务器、服务器 → 外部服务,还是服务器内部进程间?
常用测试方法(从客户端/另一台机器执行):
| 测试目标 | 推荐命令(带关键选项) | 观察重点指标 | 延迟类型初步判断 |
|---|---|---|---|
| 服务器 IP 本身 | ping -c 100 -i 0.2 server_ip | rtt min/avg/max/mdev,丢包率 | 基础链路 + 服务器内核处理延迟 |
| 服务器域名 | ping -c 100 domain.com 或 dig +stats domain.com | Query time(DNS 解析时间) + ping rtt | DNS vs 链路延迟 |
| 服务器公网出口 | ping -c 100 8.8.8.8 或 ping -c 100 1.1.1.1 | rtt 与到服务器 IP 的对比 | 服务器上行链路问题 |
| 典型外部服务 | ping -c 100 api.example.com | — | 对比判断是服务器侧还是对端/路径问题 |
| 往返路径逐跳延迟 | mtr -r -c 100 server_ip 或 traceroute -n server_ip | 每跳延迟、丢包率、抖动(jitter) | 路径中哪一跳引入延迟/丢包 |
快速结论模板:
- 到服务器 IP 的 ping avg > 50–100ms 且稳定高 → 服务器到客户端链路问题(或服务器网卡/内核处理慢)
- ping IP 正常,但 ping 域名慢 → DNS 解析瓶颈
- ping 外部 8.8.8.8 延迟高 → 服务器上行链路或出口问题
- mtr 显示某跳延迟突然跳高/丢包 → 运营商/云厂商骨干网问题
第二步:服务器本地网络栈延迟排查
当外部 ping 正常,但业务请求(HTTP/gRPC/TCP)延迟高时,重点检查服务器自身处理路径。
| 排查层级 | 核心问题点 | 关键命令 / 观察指标 | 异常阈值参考 | 常见根因与快速修复 |
|---|---|---|---|---|
| 网卡接收延迟 | 软中断处理慢、NAPI 轮询不足、IRQ 不均衡 | mpstat -P ALL 1 5(看 NET_RX 软中断 CPU) cat /proc/interrupts(看网卡中断分布) | NET_RX 在单核 > 30–50% | 1. 绑定中断到多核(irqbalance 或手工 smp_affinity) 2. 开启 busy_poll(sysctl net.core.busy_poll=50) |
| 内核协议栈延迟 | TCP 栈处理慢、连接队列满、SYN 洪水 | ss -s(看 retrans、timeouts、listen drops) `netstat -s | grep -i “listen|overflow|retrans”` | listen drops > 0 或 retrans > 1–5% |
| TCP 拥塞窗口 / RTT | 拥塞控制算法不适配、buffer 过小 | ss -ti dst remote_ip(看 rto、rtt、cwnd) sysctl net.ipv4.tcp_congestion_control | cwnd 很小、rto 高 | 切换 BBR(tcp_congestion_control = bbr) |
| 网卡 ring buffer / coalesce | 中断合并过度或不足 | ethtool -g eth0(ring buffer 大小) ethtool -c eth0(coalesce 参数) | rx-usecs 过大(>100–200)导致延迟 | 调低 rx-usecs(低延迟场景 0–50),增大 ring buffer |
| 虚拟化 / SR-IOV / DPDK | virtio_net 队列延迟、VF 竞争 | mpstat st 高 + virtio_net 软中断高 | steal > 5–10% | 调大 virtio 队列数、启用 multi-queue |
推荐调优组合(低延迟场景常用):
Bash
# 启用 BBR + 增大缓冲
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
# 低延迟中断合并(慎用,高吞吐可能下降)
ethtool -C eth0 rx-usecs 50 tx-usecs 50第三步:应用层与对端延迟
| 场景 | 判断方法 | 常见根因 | 快速验证 / 修复 |
|---|---|---|---|
| DNS 解析慢 | time dig +short api.example.com 或 resolvectl query | 上游 DNS 超时、search 域过多、缓存失效 | 换 8.8.8.8 / 1.1.1.1,启用 systemd-resolved 缓存 |
| TCP 三次握手慢 | ss -tio state syn-recv 或 tcpdump 看 SYN → SYN-ACK 时间 | SYN backlog 满、防火墙丢包 | 调大 tcp_max_syn_backlog、检查防火墙规则 |
| 应用处理慢 | strace -c -p PID 或 perf record 看 accept/read 系统调用 | accept 队列满、后端慢 | 增大 listen backlog、检查后端响应时间 |
| 对端慢 / 路径问题 | mtr / traceroute 到客户端 IP,观察哪跳延迟/丢包 | 运营商骨干网拥塞、DDoS、路由不对称 | 多线 BGP、Anycast、换 CDN 或加速线路 |
第四步:抓包深度验证
tcpdump 神器组合(低开销抓取关键点):
Bash
# 抓取新连接建立延迟
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' -nn -c 100
# 抓取特定客户端到服务器 80 端口全过程
tcpdump -i eth0 host client_ip and port 80 -w delay.pcap
# 事后用 Wireshark 看:
# - TCP 三次握手时间
# - RTT / Retransmission
# - Window Full / Zero Window
# - Application Data 发送间隔一句话排查思维模型:
先分清延迟发生在哪一段(客户端→服务器?服务器→外部?内部?) 再看服务器本地栈(网卡中断 → 协议栈 → socket 队列) 最后对比路径与对端(mtr + tcpdump 抓证据)