服务器网络延迟高怎么优化

结论: 网络延迟高不能笼统地说"网速慢",必须先分段测量、再定向优化。用 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、边缘节点),没有任何参数能让它更快——这一点决定了后面所有优化手段的选择。

测量方法论:先定位在哪一段,再谈优化

结论:严格按"端到端分解 → 逐跳定位 → 单点深挖"三步走,禁止跳过前两步直接改参数。

text
第一步:端到端分解(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(抖动)往往比平均值更能说明问题。**

bash
# 基础用法:发 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 的核心价值是同时给出每一跳的丢包率与延迟,看"延迟在哪一跳突然跳升"就能锁定问题段。

bash
# 报表模式:发 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 输出解读:

text
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 分解各阶段耗时

结论:这是判断"网络慢还是应用慢"最快的一条命令,也是本文方法论的第一步。

bash
# 一次性输出全部阶段耗时
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_namelookupDNS 解析完成= DNS 耗时
time_connectTCP 三次握手完成减去 time_namelookup = 建连耗时(≈1 RTT)
time_appconnectTLS 握手完成减去 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、重传次数、拥塞窗口与发送速率,是判断"丢包重传"的权威依据。

bash
# 查看所有已建立连接的详细 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 等缓存命中标记。