面试官:CDN是怎么加速网站访问的?

做前端项目的时候,经常听到"静态资源要放CDN"这种说法:

  • CDN到底是什么,为什么能加速?
  • 用户访问CDN的时候发生了什么?
  • 前端项目怎么配置CDN?

先说结论

CDN(Content Delivery Network)的核心原理:把内容缓存到离用户最近的服务器上

没有CDN时,北京用户访问美国服务器,数据要跨越太平洋。有了CDN,数据从北京的CDN节点返回,快得多。

flowchart LR subgraph 没有CDN U1[北京用户] -->|跨越太平洋| S1[美国服务器] end subgraph 有CDN U2[北京用户] -->|就近访问| C2[北京CDN节点] C2 -.->|首次回源| S2[美国服务器] end

CDN的工作流程

当用户访问一个CDN加速的资源时,会经过这几步:

1. DNS解析

用户访问 cdn.example.com,DNS会返回离用户最近的CDN节点IP。

bash 复制代码
# 在北京查询
$ dig cdn.example.com
;; ANSWER SECTION:
cdn.example.com.    60    IN    A    101.37.27.xxx  # 北京节点

# 在上海查询
$ dig cdn.example.com
;; ANSWER SECTION:
cdn.example.com.    60    IN    A    47.100.99.xxx  # 上海节点

同一个域名,不同地区解析出不同IP,这就是CDN的智能调度。

2. 缓存判断

请求到达CDN节点后,节点检查本地是否有缓存:

  • 缓存命中:直接返回,速度最快
  • 缓存未命中:向源服务器获取,然后缓存起来
flowchart TD A[用户请求] --> B[CDN边缘节点] B --> C{本地有缓存?} C -->|有| D[直接返回] C -->|没有| E[回源获取] E --> F[源服务器] F --> G[返回内容] G --> H[缓存到边缘节点] H --> D classDef hit fill:#d4edda,stroke:#28a745,color:#155724 classDef miss fill:#fff3cd,stroke:#ffc107,color:#856404 class D hit class E,F,G,H miss

3. 缓存策略

CDN根据HTTP头决定怎么缓存:

http 复制代码
# 典型的静态资源响应头
Cache-Control: public, max-age=31536000
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
  • max-age=31536000:缓存1年
  • public:允许CDN缓存
  • ETag:文件指纹,用于验证缓存是否过期

为什么CDN能加速

1. 物理距离更近

光在光纤中的传播速度约为 20 万公里/秒。北京到美国往返 2 万公里,光传输就要 100ms。

CDN把内容放到离用户近的地方,这个延迟几乎可以忽略。

2. 分散服务器压力

没有CDN,所有请求都打到源服务器。有了CDN,只有第一次请求(缓存未命中)才需要回源。

假设一张图片被访问 100 万次:

  • 没有CDN:源服务器处理 100 万次请求
  • 有CDN:源服务器只处理几十次(各节点首次回源)

3. 边缘节点优化

CDN服务商的边缘节点通常有这些优化:

  • 自动压缩:Gzip/Brotli压缩
  • 协议优化:HTTP/2、HTTP/3
  • 连接复用:Keep-Alive连接池
  • 智能路由:选择最优网络路径

前端项目配置CDN

1. 构建配置

以Vite为例,配置静态资源的CDN地址:

javascript 复制代码
// vite.config.js
export default defineConfig({
  base: process.env.NODE_ENV === 'production'
    ? 'https://cdn.example.com/'
    : '/',
  build: {
    rollupOptions: {
      output: {
        // 文件名带hash,便于长期缓存
        entryFileNames: 'js/[name].[hash].js',
        chunkFileNames: 'js/[name].[hash].js',
        assetFileNames: 'assets/[name].[hash].[ext]'
      }
    }
  }
})

Webpack配置类似:

javascript 复制代码
// webpack.config.js
module.exports = {
  output: {
    publicPath: process.env.NODE_ENV === 'production'
      ? 'https://cdn.example.com/'
      : '/',
    filename: 'js/[name].[contenthash].js',
  }
}

2. 上传到CDN

构建完成后,把dist目录的文件上传到CDN。大多数CDN服务商都提供CLI工具或API:

bash 复制代码
# 阿里云OSS + CDN
aliyun oss cp -r ./dist oss://your-bucket/

# AWS S3 + CloudFront
aws s3 sync ./dist s3://your-bucket/

# 七牛云
qshell qupload2 --src-dir=./dist --bucket=your-bucket

3. 缓存策略配置

关键是区分两类文件:

带hash的静态资源(JS、CSS、图片):长期缓存

nginx 复制代码
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

HTML文件:不缓存或短期缓存

nginx 复制代码
location ~* \.html$ {
    expires 0;
    add_header Cache-Control "no-cache, must-revalidate";
}

为什么这样设计?因为HTML是入口文件,它引用的JS/CSS带有hash。更新代码时:

  1. 新的JS文件会有新的hash(app.abc123.jsapp.def456.js
  2. HTML文件引用新的JS文件
  3. 用户获取新HTML后,会加载新的JS文件
  4. 旧的JS文件在CDN上继续存在,不影响正在访问的用户

4. DNS配置

把CDN域名配置成CNAME指向CDN服务商:

bash 复制代码
# 阿里云CDN
cdn.example.com.    IN    CNAME    cdn.example.com.w.kunlunsl.com.

# Cloudflare
cdn.example.com.    IN    CNAME    example.com.cdn.cloudflare.net.

常见问题

跨域问题

CDN域名和主域名不同,字体文件、AJAX请求可能遇到跨域。

解决方案是在CDN配置CORS头:

nginx 复制代码
# CDN服务器配置
add_header Access-Control-Allow-Origin "https://example.com";
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS";

或者在源服务器的响应里加上CORS头,CDN会透传。

缓存更新问题

发布新版本后,用户还是看到旧内容?

方案一:文件名带hash(推荐)

前面已经提到,文件名带hash,新版本就是新文件,不存在缓存问题。

方案二:主动刷新缓存

javascript 复制代码
// 调用CDN服务商的刷新API
await cdnClient.refreshObjectCaches({
  ObjectPath: 'https://cdn.example.com/app.js\nhttps://cdn.example.com/app.css',
  ObjectType: 'File'
});

方案三:URL加版本号

html 复制代码
<script src="https://cdn.example.com/app.js?v=1.2.3"></script>

不太推荐,因为有些CDN会忽略查询参数。

HTTPS证书

CDN域名也需要HTTPS证书。大多数CDN服务商提供免费证书或支持上传自有证书。

配置方式:

  1. 在CDN控制台申请免费证书(通常是DV证书)
  2. 或上传自己的证书(用Let's Encrypt申请)
bash 复制代码
# 用certbot申请泛域名证书
certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d "example.com"

回源优化

如果源服务器压力大,可以启用"回源加速"或"中间源":

复制代码
用户 → 边缘节点 → 中间源 → 源服务器

中间源作为二级缓存,减少对源服务器的请求。多数CDN服务商默认开启这个功能。

CDN选型

CDN服务商 优势 适用场景
阿里云CDN 国内节点多,生态完整 国内业务为主
腾讯云CDN 游戏加速好,直播支持强 游戏、直播
Cloudflare 全球节点,有免费套餐 出海业务、个人项目
AWS CloudFront 与AWS生态集成 已用AWS的项目
Vercel/Netlify 前端项目一站式部署 JAMStack项目

个人项目推荐Cloudflare,免费套餐够用,全球节点覆盖好。

企业项目根据用户分布选择。面向国内用户,阿里云/腾讯云更合适;面向全球用户,Cloudflare或CloudFront。

验证CDN效果

浏览器开发者工具

打开Network面板,关注这几个指标:

  • TTFB(Time To First Byte):首字节时间,越小越好
  • 响应头中的缓存信息X-Cache: HIT 表示命中CDN缓存

命令行测试

bash 复制代码
# 查看响应头
curl -I https://cdn.example.com/app.js

# 输出示例
HTTP/2 200
cache-control: public, max-age=31536000
x-cache: HIT from CN-Beijing

在线工具

小结

CDN加速的核心原理:

  1. 就近访问:DNS智能解析,把用户引导到最近的节点
  2. 缓存机制:边缘节点缓存内容,减少回源
  3. 协议优化:HTTP/2、压缩、连接复用

前端配置CDN的关键:

  1. 构建时配置publicPath:指向CDN域名
  2. 文件名带hash:便于长期缓存
  3. HTML不缓存:确保用户能获取到最新入口
  4. 处理跨域:配置CORS头

如果你觉得这篇文章有帮助,欢迎关注我的 GitHub,下面是我的一些开源项目:

Claude Code Skills (按需加载,意图自动识别,不浪费 token,介绍文章):

全栈项目(适合学习现代技术栈):

  • prompt-vault - Prompt 管理器,用的都是最新的技术栈,适合用来学习了解最新的前端全栈开发范式:Next.js 15 + React 19 + tRPC 11 + Supabase 全栈示例,clone 下来配个免费 Supabase 就能跑
  • chat_edit - 双模式 AI 应用(聊天+富文本编辑),Vue 3.5 + TypeScript + Vite 5 + Quill 2.0 + IndexedDB
相关推荐
姚不倒2 天前
从 A 记录到 CDN 切换:我的 DNS 认知跃迁之路
运维·cdn·dns
字节跳动视频云技术团队6 天前
AI Agent 会自己选 CDN 了:当网站访问者从 “人” 扩展到 “AI”,内容分发已升级
人工智能·cdn
Linsk6 天前
2026年了,请停止相信“公共 CDN 能提升性能”
前端·jquery·cdn
锐速网络1 个月前
游戏加速、DNS加速、CDN网络加速三者选型指南
cdn·网络优化·网络运维·游戏加速·dns加速·运维选型·长连接加速
锐速网络1 个月前
CDN视频加速集群部署与性能调优
cdn·网络优化·视频加速·流媒体加速·直播cdn·cdn集群部署·锐速安全
mCell1 个月前
别急着骂运营商,你家路由器里可能藏着一台 PCDN 盒子
前端·http·cdn
云安全干货局1 个月前
怎么选择靠谱的CDN服务品牌?主流品牌性能对比及加速效果解析
cdn·安全加速·云加速·业务加速·edge scdn
SEO_juper2 个月前
CDN 地域节点优化:匹配 GEO 信号,提升加载速度
服务器·ai·php·seo·cdn·geo·谷歌优化
Love Song残响2 个月前
PowerSetting下载慢?CDN加速 + 离线包分发综合优化方案
cdn
隔窗听雨眠2 个月前
从DNS解析到分布式存储的技术解构
分布式·网关·cdn·dns·socks