主页

CDN - 网站加速

2026-09-09 09:44AM

给网站增加 CDN 全球加速,从源站配置到全球访问优化的完整实践

最近给自己的网站增加了 CDN 全球加速。

网站前端使用 React,后端使用 Go,源站部署在中国大陆。由于网站的用户可能来自美国、日本、新加坡、欧洲等海外地区,如果所有静态资源都直接从中国大陆源站加载,海外用户访问时容易出现明显的延迟。

1. 给网站增加CDN的原因:

最开始的网站结构比较简单:

用户
 ↓
中国大陆服务器
 ↓
Nginx
 ↓
React 前端
 +
Go 后端

这种架构在中国大陆访问没有太大问题。

但是,如果用户在美国、日本、欧洲等地区:

海外用户
    ↓
跨境网络
    ↓
中国大陆源站
    ↓
返回 JS/CSS/图片等静态资源

所有资源都需要从中国大陆服务器传输到海外。

尤其是 React 网站,一个页面可能需要加载:

index.html
xxx.js
xxx.css
字体
图片
其他静态资源

如果 JS 文件比较大,就会明显影响首次打开速度。

因此需要把静态资源放到离用户更近的 CDN 节点。

2. CDN能解决的问题:

CDN 的核心思想并不复杂:

把源站上的静态资源缓存到全球各地的 CDN 节点。

eg:我的源站位于中国大陆。

没有 CDN:

美国用户
    ↓
中国大陆源站
    ↓
    JS

使用 CDN:

美国用户
    ↓
美国/附近 CDN 节点
    ↓
    JS

第一次访问时,如果 CDN 没有资源:

用户
 ↓
CDN 节点
 ↓
源站
 ↓
CDN 缓存
 ↓
用户

之后其他用户再次请求:

用户
 ↓
CDN 节点
 ↓
直接返回缓存

这样就减少了跨境回源。

3. 并不是整个网站都应该缓存:

这里是配置 CDN 时非常重要的一点。

我的网站实际上包含三类资源:

3.1. 前端静态资源

例如:

.js
.css
.png
.jpg
.jpeg
.webp
.gif
.ico
.woff
.woff2

这些资源非常适合 CDN。

3.2. HTML

例如:

index.html

HTML 和 JS/CSS 不太一样。

如果把 HTML 设置成非常长时间缓存,那么网站发布新版本之后,用户可能仍然拿到旧 HTML。

所以通常:

HTML
 ↓
短缓存 / 不缓存

而:

JS
CSS
字体
图片
 ↓
长期缓存

3.3. API

我的 API 域名是:

api.mysite.com

里面主要是 Go 后端接口,例如:

创建任务
查询任务
用户信息
积分
支付
视频生成状态

这些都是动态请求。

因此不应该简单地把 API 响应缓存到 CDN。

最终采用:

mysite.com
    ↓
   CDN

而:

api.mysite.com
    ↓
直接访问 API 源站

这样更加合理。

4. 最终采用的架构:

API方面:

用户
 ↓
api.mysite.com
 ↓
Go API 源站
 ↓
动态请求,不做 CDN 缓存

 视频:

用户
 ↓
OSS 全球加速
 ↓
MP4 视频文件

这篇文章记录整个配置过程。

5. 准备CDN加速域名

在阿里云 CDN 中创建加速域名。

例如:

mysite.com

或者根据自己的实际域名配置。

配置时需要指定:

加速域名
源站类型
源站地址
源站 HOST
HTTPS
缓存规则

这里最重要的是:

CDN 必须知道自己的源站在哪里。

例如:

CDN
 ↓
mysite.com 源站服务器

6. 配置源站

假设源站服务器是:

中国大陆服务器

网站通过 Nginx 提供 HTTPS:443

Nginx 类似:

server {
    listen 443 ssl;
    server_name mysite.com www.mysite.com;

    ssl_certificate     xxx.pem;
    ssl_certificate_key xxx.key;

    ...
}

这里需要保证:

CDN → 源站

这一段能够正常通信。

也就是说,不能只考虑:

用户 → CDN

还必须考虑:

CDN → 源站

否则 CDN 虽然创建成功,但是回源的时候仍然可能出现:

502 Bad Gateway

7. 配置 Origin Host

这是后来排查问题时非常重要的一项。

CDN 回源时,需要告诉源站:

Host: mysite.com

因此可以配置:

Default Origin HOST:开启

Custom Origin Host:
mysite.com

为什么需要这个配置?

因为 Nginx 经常根据:

Host

来匹配:

server_name

例如:

server_name mysite.com www.mysite.com;

如果 CDN 回源的时候 Host 不正确,Nginx 可能匹配不到正确的 Server。

因此:

CDN
 ↓
Host: mysite.com
 ↓
Nginx
 ↓
server_name mysite.com

这一链路必须保持一致。

8. 配置HTTPS

我的网站本身使用 HTTPS:

https://mysite.com

因此 CDN 也需要配置 HTTPS。

基本思路:

用户
 ↓ HTTPS
CDN
 ↓ HTTPS
源站

而不是:

用户
 ↓ HTTPS
CDN
 ↓ HTTP
源站

当然,CDN → 源站是否使用 HTTPS,要根据实际安全要求和源站配置决定。

如果源站本身监听:443

并且已经配置 SSL,那么可以让 CDN 使用 HTTPS 回源。

例如:

HTTPS Port: 443
Protocol: Follow Origin

9. 配置SNI

HTTPS 回源的时候,如果一个 IP 上存在多个 HTTPS 网站,就涉及 SNI。

例如:

服务器 IP
 ├── mysite.com
 ├── example.com
 └── other.com

CDN 回源时需要明确告诉服务器:

我要访问的是 mysite.com

因此可以配置:

SNI:开启
SNI:
mysite.com

这样 CDN → 源站进行 TLS 握手时,可以携带正确的域名。

10. 配置缓存规则

这是整个 CDN 配置中最重要的一步之一。

我给网站设置的核心思路是:

HTML
 ↓
不长期缓存

JS
 ↓
长期缓存

CSS
 ↓
长期缓存

图片
 ↓
长期缓存

字体
 ↓
长期缓存

MP4
 ↓
根据实际存储方式处理

例如:

css
js
mp4
jpg
jpeg
png
webp
gif
ico
woff
woff2

可以设置比较长的缓存时间。

例如 React 项目经常会生成:

assets/index-8a7f23.js
assets/index-91c2ab.css

这种文件名带 hash 的静态资源非常适合长期缓存。

因为代码更新之后:

index-8a7f23.js

会变成:

index-c91d821.js

新旧文件名不同,因此可以安全地设置:

Cache-Control: max-age=31536000, immutable

也就是大约一年。

11. HTML 不建议设置一年缓存

例如:

index.html

如果设置:

max-age=31536000

那么用户可能长时间拿不到最新 HTML。

因此更合理的是:

index.html
 ↓
no-cache

或者设置较短的缓存时间(eg:一个月)。

这样用户访问:

mysite.com

时,可以更及时获得最新版本。

而 HTML 引用的:

xxx.js
xxx.css

仍然可以从 CDN 高速获取。

12. DNS 切换

CDN 配置完成以后,并不是马上所有用户都会经过 CDN。

还需要修改 DNS。

原来的结构可能是:

mysite.com
 ↓
 A
 ↓
源站 IP

配置 CDN 后,需要变成:

mysite.com
 ↓
CNAME
 ↓
CDN 加速域名
 ↓
CDN 节点
 ↓
源站

也就是说:

用户
 ↓
DNS
 ↓
CDN

而不是:

用户
 ↓
DNS
 ↓
源站 IP

13. CND配置时需要特别注意

这一部分我实际遇到过问题。

当时某个 DNS CNAME 配置启用后:

Chrome
 ↓
502 Bad Gateway

但是:

Chrome 无痕模式
 ↓
正常

Firefox:

正常

后来排查发现,问题和 DNS/CDN 配置有关。

因此配置 CDN 后,如果出现:

502

不要马上认为是 CDN 本身坏了。

需要分别检查:

DNS
 ↓
CDN
 ↓
CDN 回源
 ↓
Nginx
 ↓
HTTPS
 ↓
应用

14. CDN 出现 502 时怎么排查

可以按照这个顺序排查。

14.1. 先确认源站是否正常

直接访问源站。

例如:

curl -I https://mysite.com

如果源站本身就是:

HTTP/2 200

说明源站基本正常。

14.2. 检查 Nginx

确认:

443

是否监听。

例如:

ss -lntp | grep 443

同时检查:

server_name
ssl_certificate
ssl_certificate_key

14.3 检查防火墙

确保 CDN 节点能够访问源站:

TCP 443

不能只保证自己的电脑可以访问

14.4 检查 Origin Host

确认:

Host: mysite.com

和 Nginx:

server_name mysite.com;

能够对应。

14.5 检查 SNI

HTTPS 回源出现问题时,检查:

SNI

是否开启,并确认:

SNI = mysite.com

14.6 使用 curl 测试

例如:

curl -I https://mysite.com

也可以使用:

curl -v https://mysite.com

 查看:

DNS
TCP
TLS
HTTP

整个过程。

15. 如何判断 CDN 到底有没有生效?

这是非常重要的一步。

不能仅仅看到:

HTTP 200

就认为 CDN 已经生效。

因为:

源站 200

和:

CDN 200

是两回事。

需要查看 HTTP 响应头。

例如后来测试 JS 文件时,看到类似:

server: Tengine
content-type: application/javascript
cache-control: max-age=31536000 public, max-age=31536000, immutable
age: 88
x-cache: HIT
TCP_MEM_HIT

其中非常关键的是:

x-cache: HIT

以及:

TCP_MEM_HIT

这说明:

CDN 节点已经命中缓存,并直接从 CDN 返回资源。

也就是说:

用户
 ↓
CDN
 ↓
缓存中的 JS

而不是:

用户
 ↓
CDN
 ↓
源站
 ↓
 JS

 16. 为什么第一次请求可能 MISS?

刚配置 CDN 时,第一次访问一个资源:

用户
 ↓
CDN
 ↓
发现没有缓存
 ↓
源站
 ↓
返回资源
 ↓
CDN 缓存
 ↓
用户

这时候可能看到:

x-cache: MISS

第二次:

用户
 ↓
CDN
 ↓
缓存
 ↓
用户

可能变成:

x-cache: HIT

所以:

MISS

并不意味着 CDN 配置失败。

17. HTML 出现 MISS 也不一定是问题

我的网站后来测试 HTML 时出现过:

x-cache: MISS
TCP_MISS

同时 HTML 设置了:

Cache-Control: no-cache

这种情况下 CDN 不长期缓存 HTML 是符合预期的。

真正需要重点关注的是:

JS
CSS
图片
字体
视频

这些静态资源是否能够:

HIT

18. MP4 应该怎么处理?

我的网站还有大量 AI 视频生成后的 MP4。

这类文件不建议简单地和普通 HTML 一样处理。

我的视频文件放在:

Alibaba Cloud OSS

并且 OSS 已经配置了全球域名加速。

因此采用:

用户
 ↓
OSS 全球加速
 ↓
MP4

而网站静态资源:

用户
 ↓
CDN
 ↓
JS/CSS/图片/字体

这样可以把:

网站静态资源

和:

大文件视频

分别进行优化。

19. 配置完成以后, 进行测试全球速度

最后不能只在自己的电脑上测试(可以在阿里云的无影云上面进行测试,需要付费)

因为 CDN 的核心目的就是:改善全球不同地区用户访问网站的速度

因此应该测试:

中国大陆
香港
日本
新加坡
韩国
美国
加拿大
英国
德国
法国
澳大利亚

重点观察:

DNS
TCP
TLS
TTFB
页面加载时间
JS 下载时间
CSS 下载时间

尤其是:

TTFB

和:

页面完全加载时间

可以比较:

CDN 前
VS
CDN 后

这样才能真正判断 CDN 是否有效。

20. 总结:

给网站增加 CDN,并不是简单地:

购买 CDN
↓
修改 DNS
↓
结束

完整流程应该是:

① 分析网站架构
        ↓
② 区分静态资源和动态 API
        ↓
③ 创建 CDN 加速域名
        ↓
④ 配置源站
        ↓
⑤ 配置 Origin Host
        ↓
⑥ 配置 HTTPS
        ↓
⑦ 配置 SNI
        ↓
⑧ 配置缓存规则
        ↓
⑨ 配置 DNS CNAME
        ↓
⑩ 等待 DNS 生效
        ↓
⑪ 测试 CDN 是否正常回源
        ↓
⑫ 检查 HTTP 响应头
        ↓
⑬ 确认 x-cache HIT
        ↓
⑭ 全球不同地区测速
        ↓
⑮ 根据测试结果继续优化

对于我的 mysite.com 来说,最终采用的是:

┌───────────────────┐
│             mysite.com               │
│                                      │
│  React 前端                          │
│  JS / CSS / 图片 / 字体              │
│              ↓                      │
│          阿里云 CDN                  │
│              ↓                      │
│          全球 CDN 节点               │
└───────────────────┘


┌───────────────────┐
│          api.mysite.com              │
│                                      │
│              Go API                  │
│              ↓                      │
│           直接源站                   │
│                                      │
│        CDN 不缓存动态 API            │
└───────────────────┘


┌───────────────────┐
│              MP4 视频                │
│                                      │
│              OSS                     │
│               ↓                     │
│           全球加速                   │
└───────────────────┘

这样做的核心目的不是“让所有请求都经过 CDN”,而是:

让最适合缓存的静态资源尽可能在距离用户更近的 CDN 节点提供,同时让动态 API 保持正常的实时请求,让大体积视频通过 OSS 全球加速传输。

 

返回>>

登录

请登录后再发表评论。

评论列表:

目前还没有人发表评论