结论: 网络延迟高不能笼统地说"网速慢",必须先分段测量、再定向优化。用 curl -w 把一次请求拆成 DNS 解析、TCP 建连、TLS 握手、服务端处理(TTFB)、内容传输五段,哪段大就优化哪段:DNS 慢就换解析器并加缓存,建连慢就上 CDN 就近接入与 TCP 参数调优,传输慢就开 BBR、调大窗口、启用 HTTP/2 或 HTTP/3。跨段平均用力的做法,通常花两周也只能快 10%。
延迟优化最容易犯的错误是"未测量就优化"。运维同学常见的第一反应是加带宽,但带宽决定的是单位时间能传多少,延迟决定的是第一个字节多久到,两者是不同的指标——一个 100 Mbps 的链路和中缅跨境路由的 300 ms 延迟毫无关系。本文以 Ubuntu 24.04 LTS + Nginx 1.26 为环境(截至 2026 年主流版本),给出从测量到优化的完整链路。
延迟由哪几段构成:先建立分段模型
结论:一次 HTTPS 请求的耗时可以精确拆成五段,先算出各段占比,优化才有靶子。
| 阶段 | 含义 | 典型正常值 | 偏高时首查 |
|---|---|---|---|
| DNS 解析 | 域名 → IP | < 50 ms(有缓存时 < 5 ms) | 解析器质量、TTL、缓存 |
| TCP 建连 | 三次握手完成 | 1 个 RTT(同城 1~5 ms,跨省 20~50 ms) | 物理距离、链路质量 |
| TLS 握手 | 证书交换与密钥协商 | 1~2 个 RTT(TLS 1.3 为 1 RTT) | TLS 版本、会话复用 |
| 服务端处理(TTFB) | 请求到首字节 | 动态页 50~300 ms | 应用性能、数据库查询 |
| 内容传输 | 首字节到最后字节 | 取决于体积与带宽 | 压缩、分片、CDN |
从物理层面看,延迟又可以归为四类,这是判断"能不能优化"的理论上限:
| 类型 | 定义 | 典型量级 | 可否优化 |
|---|---|---|---|
| 传播延迟 | 信号在介质中传播的时间,光纤约 4.9 μs/km | 跨省 5~15 ms,中美 50~80 ms | 不可优化,只能靠缩短物理距离 |
| 传输延迟 | 把数据推上链路的时间 = 数据量 ÷ 带宽 | 1 MB @ 10 Mbps ≈ 0.8 s | 可优化(加带宽、压缩) |
| 处理延迟 | 路由器/防火墙/服务器处理分组的时间 | 每跳 0.1~2 ms | 部分可优化(减少中间设备) |
| 排队延迟 | 链路拥塞时在队列中等待的时间 | 波动最大,拥塞时可达数百 ms | 可优化(BBR、QoS、扩容) |
传播延迟是硬上限:北京到上海直线约 1200 km,光纤单程约 6 ms,往返理论下限约 12 ms,实际路由绕行通常在 25~40 ms。如果你的实测值已经接近理论下限,那么除了把服务器搬到用户附近(CDN、边缘节点),没有任何参数能让它更快——这一点决定了后面所有优化手段的选择。
测量方法论:先定位在哪一段,再谈优化
结论:严格按"端到端分解 → 逐跳定位 → 单点深挖"三步走,禁止跳过前两步直接改参数。
第一步:端到端分解(curl -w) → 确定慢在 DNS、建连、服务端还是传输
第二步:逐跳定位(ping / mtr) → 确定慢在客户端、运营商、骨干网还是机房
第三步:单点深挖(ss -i / 抓包) → 确定是丢包重传、窗口受限还是应用处理慢三步之间不能跳跃。举例:如果 curl -w 显示 time_starttransfer 高达 2 秒,而 time_connect 只有 20 ms,那问题根本不在网络上,去优化 TCP 参数毫无意义——应该去查数据库慢查询。
ping RTT 怎么读:不只是看平均值
结论:ping 看四个数——min/avg/max/mdev,其中 mdev(抖动)往往比平均值更能说明问题。**
# 基础用法:发 20 个包看统计
ping -c 20 www.example.com
# 输出示例:20 packets transmitted, 20 received, 0% packet loss, time 19028ms
# rtt min/avg/max/mdev = 28.114/29.332/45.201/4.221 ms
# 指定间隔与包大小(排查 MTU 与分片问题时用大包)
ping -i 0.2 -s 1472 -c 50 www.example.com
# 记录路由(部分网络不支持)
ping -R -c 5 www.example.com| 场景 | 正常 RTT 参考 | 说明 |
|---|---|---|
| 同机房 / 同可用区 | < 1 ms | 内网互通,超过 1 ms 需查交换机 |
| 同城不同机房 | 1~5 ms | 光纤直连,多绕一跳约 +1 ms |
| 国内跨省(骨干网) | 20~50 ms | 与物理距离和运营商互通质量相关 |
| 中国大陆 → 中国香港 | 30~80 ms | 跨境出口与海缆走向影响大 |
| 中国大陆 → 美西 | 150~250 ms | 跨太平洋,接近传播延迟上限 |
| 中国大陆 → 欧洲 | 200~320 ms | 经美转或经俄欧陆缆差异明显 |
判读要点:
mdev大于avg的 30% 说明抖动严重,常见于无线网络、跨境链路或拥塞链路,对实时业务(语音、游戏、交易)影响远大于稳定的高延迟。max远大于avg说明存在偶发排队,通常是链路瞬时拥塞或某跳设备 CPU 打满。- 丢包率超过 1% 就需要重视:TCP 会把丢包解读为拥塞并降低发送速率,1% 丢包可能让吞吐下降一半以上。
- ping 通不代表业务通:很多机房禁 ICMP,ping 全丢而网页正常是常见现象,此时要用 TCP 模式测(
mtr --tcp -P 443)。
mtr 逐跳定位:找到从哪一跳开始劣化
结论:mtr 的核心价值是同时给出每一跳的丢包率与延迟,看"延迟在哪一跳突然跳升"就能锁定问题段。
# 报表模式:发 100 个包后输出统计(最常用)
mtr --report --report-cycles 100 www.example.com
# 关掉反向 DNS 解析,输出更快更干净
mtr -n --report -c 100 www.example.com
# ICMP 被禁时改用 TCP SYN 探测 443 端口
mtr --tcp -P 443 -n --report -c 100 www.example.com
# 传统 traceroute(mtr 相当于它的持续统计版)
traceroute -n -w 2 -q 3 www.example.com
traceroute -T -p 443 -n www.example.com # TCP 模式,穿透禁 ICMP 的网络典型 mtr 输出解读:
Host Loss% Snt Last Avg Best Wrst StDev
1. 192.168.1.1 0.0% 100 0.8 0.9 0.6 3.2 0.3
2. 10.100.0.1 0.0% 100 3.1 3.4 2.8 8.1 0.7
3. 221.xxx.xxx.1 0.0% 100 4.2 4.5 3.9 12.0 0.9
4. 202.97.xx.xx 0.0% 100 28.6 29.1 27.4 38.2 1.6 ← 延迟从此跳开始跳升
5. 202.97.xx.yy 2.1% 100 29.8 30.5 28.1 52.4 3.1 ← 且开始丢包
6. 目标服务器 2.3% 100 30.2 31.0 28.6 55.1 3.4三种典型模式与结论:
| 模式 | 表现 | 结论 |
|---|---|---|
| 延迟在中间某跳跳升,后续跳保持 | 第 3 跳 4 ms、第 4 跳 29 ms、之后仍在 30 ms | 该跳就是跨境/跨运营商出口,属正常物理跳变,只能靠就近部署规避 |
| 某跳丢包,且后面所有跳都丢 | 第 5 跳起 Loss% 持续 2% | 该跳设备限速或拥塞,真实故障点 |
| 只有中间某跳丢包,最后一跳 0% | 第 4 跳 5%,第 6 跳 0% | 该跳设备限速 ICMP 探测(常见),非真实丢包,可忽略 |
最后一条非常关键:看到中间跳丢包先别慌,只要最后一跳(目标服务器)丢包为 0,说明端到端路径是通的,中间跳的 Loss% 多半是运营商设备对 ICMP 做了限速。
curl -w 分解各阶段耗时
结论:这是判断"网络慢还是应用慢"最快的一条命令,也是本文方法论的第一步。
# 一次性输出全部阶段耗时
curl -o /dev/null -s -w '
DNS解析 : %{time_namelookup}s
TCP建连 : %{time_connect}s
TLS握手 : %{time_appconnect}s
预处理完成 : %{time_pretransfer}s
首字节TTFB : %{time_starttransfer}s
总耗时 : %{time_total}s
下载速度 : %{speed_download} B/s
' https://www.example.com/
# 复用连接测第二次(验证会话复用是否生效)
curl -o /dev/null -s -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_total}\n' \
https://www.example.com/ https://www.example.com/各字段的真实含义(注意它们是累计值,不是每段独立值):
| 字段 | 累计到 | 本段耗时算法 |
|---|---|---|
time_namelookup | DNS 解析完成 | = DNS 耗时 |
time_connect | TCP 三次握手完成 | 减去 time_namelookup = 建连耗时(≈1 RTT) |
time_appconnect | TLS 握手完成 | 减去 time_connect = TLS 耗时(TLS 1.2 约 2 RTT,1.3 约 1 RTT) |
time_starttransfer | 收到第一个字节 | 减去 time_appconnect = 服务端处理耗时(TTFB) |
time_total | 全部完成 | 减去 time_starttransfer = 内容传输耗时 |
判定规则:
- DNS 超过 100 ms:换公共解析器(如
223.5.5.5、119.29.29.29)或在 Nginx 里配resolver缓存。 - 建连耗时大:物理距离或链路质量问题,上 CDN 或就近部署。
- TTFB 大但建连正常:这是应用慢不是网络慢,去查数据库、代码与磁盘 IO。
- 传输耗时长:压缩(gzip/brotli)、减小资源体积、分片并行下载。
ss -i 看重传与拥塞窗口:判断链路是否真拥塞
结论:ss -i 能直接看到每条连接的 RTT、重传次数、拥塞窗口与发送速率,是判断"丢包重传"的权威依据。
# 查看所有已建立连接的详细 TCP 内部信息
ss -ti state established
# 只看目标端口 443 的连接
ss -ti state established '( sport = :443 or dport = :443 )'
# 统计各状态的连接数(TIME_WAIT 过多也会影响新连接建立)
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# 查看内核级 TCP 统计(重传总量)
netstat -s | grep -i "retransmit\|listen"ss -ti 输出中关键字段的解读:
| 字段 | 含义 | 异常判据 |
|---|---|---|
rtt:30.1/2.2 | 平滑 RTT / RTT 波动(ms) | 波动值超过 RTT 的一半说明抖动大 |
cwnd:10 | 拥塞窗口(单位为 MSS 数量) | 长期很小说明被丢包压制,吞吐上不去 |
ssthresh:20 | 慢启动阈值 | 频繁回落到低值说明反复丢包 |
retrans:0/3 | 当前重传数 / 总重传数 | 非 0 即存在丢包,持续上涨即为链路问题 |
lost:1、sacked:2 | 丢失与选择性确认段数 | 与 retrans 一起判断丢包程度 |
rto:204 | 重传超时时间(ms) | 持续偏高说明 RTT 抖动严重 |
send 4.5Mbps | 实测发送速率 | 远低于带宽上限说明窗口或拥塞受限 |
wscale:7,7 | 窗口扩大因子 | 为 0 说明未启用窗口扩大,高延迟链路吞吐受限 |
bbr / cubic | 当前拥塞控制算法 | 未显示 bbr 说明未启用 |
如果 retrans 持续非 0 且 cwnd 长期偏小,说明链路存在真实丢包——这时加带宽无效,应该换线路、上 CDN 或开启 BBR 改善拥塞判断。
优化手段一:就近部署与 CDN
结论:缩短物理距离是唯一能突破传播延迟上限的手段,也是效果最显著的优化。
- 用户集中在某一区域,就把服务器放在该区域的机房;全国分布就上 CDN,把静态资源缓存到边缘节点。
- 动态请求可用"动态加速":CDN 节点与源站之间走优化过的专线,比公网直连更稳定。
- 跨境业务优先考虑中国香港、新加坡、日本等接入点,并实测而非凭经验选点。
CDN 生效后的验证方法很简单:对比 time_connect 与 time_starttransfer 是否下降,并用 curl -I 看响应头是否出现 X-Cache: HIT、Age 等缓存命中标记。
企业QQ咨询




