面试官: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
相关推荐
Youyzq9 小时前
前端项目发布到cdn上css被编译失效问题rgba失效和rgb失效
前端·css·算法·cdn
天翼云开发者社区4 天前
一种高并发下的自旋锁优化方案
cdn
linweidong4 天前
网易ios面试题及参考答案(上)
ios·cdn·进程状态·虚拟内存·raii·网络链路·dns系统
xuchaoxin137512 天前
cdn节点代理的副作用@fail2ban对接cdn封锁恶意请求ip@fail2ban封锁ip有效性问题
运维·网络·cdn·cloudflare
斯文~15 天前
「玩透ESA」站点配置阿里云ESA全站加速+自定义规则缓存
阿里云·缓存·云计算·cdn·esa
斯文~20 天前
「玩透ESA」2025阿里云ESA初测
阿里云·cdn·esa·编译新程
天翼云开发者社区1 个月前
使用CDN时如何防劫持
cdn
天翼云开发者社区1 个月前
使用CDN后如何更新同名文件
cdn
云动雨颤1 个月前
服务器有哪些功能?网站托管/CDN加速/云计算部署必知方案
服务器·云计算·cdn