后端 2ms,页面 7 秒:一次 CDN“帮倒忙“的排查实录

线上 H5 页面加载慢到离谱------静态资源 6 秒、API 接口 7 秒。服务器在国内,CDN 也配了,后端接口只要 2ms......慢在哪?

排查下来踩了三个坑:CDN 源站配了已下线的 IP动态接口也走了 CDN新域名 DNS 又解析到了旧 IP

三个坑的根因都一样------之前做过一次服务器缩容,机器下线了,但 CDN 源站、DNS 解析这些关联配置没同步清理,埋下了三颗"定时炸弹",直到这次部署新应用才全部引爆。


一、问题现象

部署应用后,访问 H5 页面加载非常慢。F12 看 Network:

  • 静态资源(JS/CSS):单个文件加载 6 秒+
  • API 接口(JSON):多个接口响应超过 5 秒

环境信息:

  • 应用服务器:阿里云 ECS(国内)
  • CDN:阿里云 CDN(已配置)
  • 用户位置:国内
  • 前端现状 :静态资源和 API 接口共用同一个 www 域名,全部走 CDN

二、排查过程

1. 排除后端问题(2ms,无辜躺枪)

用 curl 测一个典型 API 接口的各阶段耗时(curl 更多用法可参考 curl 实战:程序员必备的接口调试与性能排查利器):

shell 复制代码
curl -o /dev/null -s -w "\nDNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\n总耗时: %{time_total}s\n" \
  'https://www.example.com/api/v1/config' \
  -H 'Content-Type: application/json' \
  --data-raw '{"id":"123","code":"test"}'
复制代码
DNS:  0.051s
TCP:  1.064s    ← TCP 连接就花了 1 秒
TLS:  1.089s
TTFB: 7.321s    ← 首字节 7 秒
总耗时: 7.322s

名词解释(看懂这几个指标,排查网络问题事半功倍):

指标 全称 含义 慢了说明什么
DNS DNS Lookup 域名解析耗时 DNS 服务器慢或解析链路长
TCP TCP Connect TCP 三次握手耗时 服务器远或网络链路差
TLS TLS Handshake SSL/TLS 握手耗时 证书链太长或未启用 TLS 1.3
TTFB Time To First Byte 从请求发出到收到第一个字节的时间 最关键指标------包含了 DNS + TCP + TLS + 服务端处理 + 网络传输
总耗时 Total Time 整个请求从发出到完成 TTFB 小但总耗时大 = 响应体太大或带宽不足

初步看 TTFB 7 秒,像是后端慢。但查了 SkyWalking 链路日志和 Nginx 日志:

log 复制代码
[request_time=0.002][upstream_time=0.002]

后端 1ms,Nginx 2ms,完全没问题。7 秒不在服务端。

2. 排除网络链路问题(9ms,也没问题)

shell 复制代码
ping www.example.com        # 9ms
sudo mtr -r -c 20 www.example.com  # 全程最高 20ms
dig www.example.com         # 解析到 kunlunaq.com(阿里云 CDN)
指标 结果 判断
ping 延迟 9ms 国内正常
mtr 全程 最高 20ms 正常
dig 解析 阿里云 CDN 节点 走了 CDN

网络链路也没问题。

3. 关键对比:走 CDN vs 直连源站(真相大白)

--resolve 绕过 CDN,直连源站 IP 做对比测试:

shell 复制代码
# 走 CDN(域名自然解析到 CDN 节点)
curl -o /dev/null -s -w "TCP: %{time_connect}s\nTTFB: %{time_starttransfer}s\n" \
  'https://www.example.com/api/v1/config' ...

# 直连源站(绕过 CDN)
curl -o /dev/null -s -w "TCP: %{time_connect}s\nTTFB: %{time_starttransfer}s\n" \
  --resolve www.example.com:443:源站IP \
  'https://www.example.com/api/v1/config' ...

API 接口对比

路径 TCP TTFB 结论
走 CDN 12ms 7 秒 CDN 回源巨慢
直连源站 48ms 165ms 源站没问题
Nginx upstream_time - 2ms 后端没问题

静态资源对比

路径 TTFB 总耗时 下载速度
走 CDN 6.2s 6.35s 72 KB/s
直连源站 0.16s 0.36s 1.2 MB/s

CDN 比直连慢了 40 倍。问题 100% 在 CDN 层。

进一步检查 CDN 缓存头:

复制代码
Content-Length: 459201         ← 没有 gzip 压缩,460KB 原文传输
Age: 0                        ← 每次都回源验证
X-Cache: HIT TCP_REFRESH_HIT  ← 缓存命中但回源验证(304),验证这一趟花了 6 秒

三、坑 1:CDN 源站配了已下线的 IP

查看阿里云 CDN 控制台的源站配置:

源站配了 6 个 IP,其中 3 个是之前缩容已下线的服务器。 CDN 回源时轮询到这些不可用 IP,连接超时后才切到正常节点,导致回源耗时 6~7 秒。

修复:删除旧 IP

在 CDN 控制台删除 3 个已下线的 IP,只保留在线的服务器。

静态资源从 6 秒降到 700ms,改善明显。但 API 仍比直连慢 8 倍:

指标 修复前 删旧 IP 后
API TTFB 7 秒 1.27 秒(直连只要 165ms)
静态资源 TTFB 6.2 秒 722ms

→ API 还是慢,因为 POST 请求也在走 CDN 绕路。


四、坑 2:动静未分离,API 请求也走了 CDN

前端的静态资源和 API 接口共用同一个 www 域名:

复制代码
nslookup www.example.com
→ www.example.com.w.kunlunaq.com  (CDN 节点)

所有 POST API 请求也先到 CDN,CDN 再回源到 ECS------多绕了一圈。CDN 本身是为静态资源加速设计的,对动态 POST 请求不但没有加速效果,反而因为回源增加了延迟。

修复:动静分离

域名 用途 是否走 CDN
www.example.com H5 页面 + 静态资源(JS/CSS/图片) ✅ 走 CDN
api.example.com 后端 API 接口 ❌ 直连源站

前端修改 API 的 base URL 指向 api.example.com,DNS 直接解析到源站 ECS IP,不经过 CDN。

同时优化了两个次要问题:

  • Nginx 配置静态资源长缓存Cache-Control: public, max-age=2592000, immutable,解决 CDN 每次回源验证的问题
  • 开启 gzip 压缩:460KB JS 压缩后约 120KB

切完域名,发布------然后,又挂了。


五、坑 3:新域名的 DNS 也解析到了旧 IP

切完 api.example.com 后,页面上所有接口直接 pending。

用 curl 一测,TCP 连接直接卡了 75 秒:

复制代码
DNS:  0.008s     ← DNS 正常
TCP:  75.054s    ← TCP 连接 75 秒!连不上
TTFB: 75.154s
总耗时: 75.154s

DNS 只要 8ms,但 TCP 75 秒------域名解析到的 IP 不对。有了之前的经验,第一时间去查 DNS:

果然,api.example.com 的 DNS 记录还指向了 3 台已下线的服务器 IP------同一个坑,第三次踩

修复:关闭旧 DNS 记录

关闭 3 条旧解析记录后恢复正常:

复制代码
DNS:  0.002s
TCP:  0.045s     ← 45ms,正常了
TTFB: 0.144s     ← 144ms,完美
总耗时: 0.144s

六、效果对比

指标 最初 修坑 1 后 修坑 2 + 3 后
API 接口 TTFB 7 秒 1.27 秒 144ms
静态资源 TTFB 6.2 秒 722ms ~200ms
页面请求数 N 个 N 个 N 个(后续 CORS 优化后减半,见第八节)
页面整体加载 10 秒+ 3~4 秒 1~2 秒

七、经验总结

三个坑,根因都是一样的:服务器缩容后,关联配置没清理干净。

在哪漏了 后果
坑 1 CDN 源站 IP 回源超时 6~7 秒
坑 2 架构层面:动静未分离 POST 请求白白绕 CDN
坑 3 DNS 解析记录 TCP 连接 75 秒

缩容后必须检查的配置清单

检查项 说明
CDN 源站 IP 删除已下线的 IP
DNS 解析记录 关闭/删除指向旧 IP 的记录
负载均衡后端 移除已下线的服务器
监控 target 清理不存在的采集目标
防火墙/安全组 清理旧 IP 的白名单规则

排查方法论

页面慢的时候,别急着怀疑后端------先用 curl -w 分段计时,再用 --resolve 绕过 CDN 对比。TCP 连接 75 秒?那一定不是后端的锅。

curl 的更多实战用法,可以参考:curl 实战:程序员必备的接口调试与性能排查利器


八、额外优化:干掉 CORS 预检请求

动静分离后,前端从 www.example.com 请求 api.example.com 的接口,触发了跨域。浏览器对每个 API 请求都先发一次 OPTIONS 预检请求(Preflight),相当于每个接口调用变成了两次请求:

预检请求本身也要走一次完整的 TCP + TLS + 后端处理,耗时和真实请求差不多------等于页面加载时间直接翻倍

修复:让浏览器缓存 CORS 策略

后端响应头加上 Access-Control-Max-Age,告诉浏览器"这个跨域策略 24 小时内有效,不用每次都问我":

java 复制代码
// Spring Boot CORS 配置
conf.setMaxAge(Duration.ofDays(1));  // 缓存 24 小时

对应的响应头:

http 复制代码
Access-Control-Max-Age: 86400

效果立竿见影------刷新页面,预检请求全部消失:

动静分离带来的"副作用":分了域名就有跨域,有跨域就有预检。记得加 Access-Control-Max-Age,否则优化了半天的 TTFB,全被预检请求吃回去了。


附:常见问题

mtr 报错 Failure to start mtr-packet: Invalid argument

需要 root 权限:

shell 复制代码
sudo mtr -r -c 20 www.example.com
相关推荐
lifewange6 小时前
RPC 是什么
网络·网络协议·rpc
Gofarlic_oms110 小时前
利用API实现ANSYS许可证管理自动化集成
运维·服务器·开发语言·matlab·自动化·负载均衡
档案宝档案管理11 小时前
权限分级管控,全程可追溯,筑牢会计档案安全防线
运维·网络·人工智能
Smart-佀12 小时前
涨薪秘技:智能家居中的BLE协议与实现
网络·arm开发·嵌入式硬件·microsoft
南京码讯光电技术有限公司12 小时前
工业级CPE,4G/5G+WiFi融合,破解严苛环境无线覆盖难题
网络·5g
倔强的石头10613 小时前
【Linux指南】基础IO系列(八):实战衔接 —— 给微型 Shell 添加完整重定向功能
linux·运维·服务器
ai_coder_ai13 小时前
在自动化脚本中如何实现网络访问?
网络·autojs·自动化脚本·冰狐智能辅助·easyclick
观北海13 小时前
AiScan-N:AI全自动化渗透测试工具的深度技术解析
运维·自动化
Ujimatsu13 小时前
虚拟机安装Ubuntu 26.04.x及其常用软件(2026.4)
linux·运维·ubuntu
被摘下的星星15 小时前
路由选择协议技术
网络·智能路由器