计算机网络:什么是 CDN?为什么它可以做缓存?

#计算机网络#操作系统#面试八股

计算机网络:什么是 CDN?为什么它可以做缓存?

结论:CDN(Content Delivery Network,内容分发网络)把内容副本提前放到离用户更近的边缘节点,再用调度把请求引到最近节点, 从而降低 RTT、分担源站带宽。它能做缓存,是因为 HTTP 本身就定义了可缓存语义,而 CDN 拿到的恰好是"可复用的静态响应"。

1. 一次请求怎么走到边缘

用户 --① 访问 www.example.com--> 本地 DNS
本地 DNS --② 递归查询--> 权威 DNS(返回 CNAME: www.example.com.cdn.net)
本地 DNS --③ 查询 cdn.net--> GSLB 按地域/运营商/负载选节点
本地 DNS --④ 返回边缘节点 IP--> 用户
用户 --⑤ 直连边缘节点(通常 10~30 ms)--> 边缘节点
边缘节点 --⑥ 未命中则回源--> 源站,拉取后缓存

调度层是 CDN 的一半:DNS 调度(CNAME + GSLB,按 EDNS Client Subnet 判断用户位置)、Anycast(同一 IP 全球广播, 由路由把人带到最近节点),以及 HTTP 302 调度(少见但存在)。

另一半是缓存层:边缘节点命中就直接返回,不命中才回源,并把响应按缓存键存下来给下一个人用。

2. 缓存能不能做,看响应头

响应头语义边缘节点行为
Cache-Control: max-age=36001 小时内新鲜缓存 1 小时
Cache-Control: s-maxage=600只对共享缓存生效覆盖 max-age,仅 CDN 用
Cache-Control: no-cache可存,但每次要回源验证存,但带 If-None-Match 回源
Cache-Control: no-store任何缓存都不得保存直接透传,不落盘
Cache-Control: private仅终端浏览器可缓存边缘不缓存
ETag / Last-Modified内容指纹 / 修改时间用于协商,命中返回 304
Vary: Accept-Encoding按编码分副本缓存键增加该维度
Set-Cookie会话相关一般导致不缓存

所以"为什么能缓存"的答案很朴素:HTTP 用 Cache-Control 与验证器把"能不能存、能存多久、怎么验"都标准化了, CDN 只是把这个规范执行到离用户最近的机器上。

3. 用 nginx 搭一个迷你边缘节点

proxy_cache_path /data/cache levels=1:2 keys_zone=edge:100m
                 max_size=10g inactive=2h use_temp_path=off;

server {
    listen 80;
    server_name edge.example.com;

    location /static/ {
        proxy_cache            edge;
        proxy_cache_key        $scheme$host$request_uri;
        proxy_cache_valid      200 302 10m;
        proxy_cache_valid      404 1m;
        proxy_cache_use_stale  error timeout updating http_500 http_502;
        proxy_cache_lock       on;              # 同一 key 只放一个回源请求
        proxy_cache_background_update on;       # 过期后先返回旧内容,后台刷新
        add_header X-Cache-Status $upstream_cache_status;  # HIT / MISS / STALE / EXPIRED
        proxy_pass http://origin_pool;
    }

    location /api/ {
        proxy_cache off;                        # 动态接口默认不缓存
        proxy_pass http://origin_pool;
    }
}

X-Cache-Status 是排查命中率的关键:大量 MISS 时先看是不是缓存键里混进了随机参数或 Cookie。

4. 常见追问

Q:发版后怎么让 CDN 立刻生效? 两条路:文件名带内容哈希(app.3f9c2a.js)配合长缓存,发版即换 URL,天然绕过旧副本; 或者调 CDN 的刷新接口按 URL / 目录清理。前者是工程首选,后者用于入口 HTML 这类不能改名的资源。

Q:命中率低怎么排查? 依次看:缓存键是否含随机 query / 时间戳;是否透传了 Cookie 导致不缓存;TTL 是否过短; 是否大量 Range 请求;回源是否因为 Vary 维度爆炸。把 X-Cache-Status 打点统计,比猜快得多。

Q:动态 API 能放 CDN 吗? 可以,但要精确:短 TTL(如 1~5 秒)、按用户或租户分键、只缓存幂等的 GET; 私有内容用签名 URL + 短过期时间,避免把 A 用户的数据发给 B 用户。

Q:CDN 只是"缓存"吗? 不。它还做 TLS 终止与证书管理、HTTP/2 与 HTTP/3 接入、gzip / brotli 压缩、图片转码、 回源长连接复用、WAF 与 DDoS 清洗。缓存只是最容易被感知的那部分。

Q:CDN 会不会缓存错误页? 会,如果响应头允许。所以通常给 5xx 设很短的 TTL 或不缓存,只对 404 设 1 分钟这类短缓存, 避免一次源站故障被放大成持续几分钟的全站错误。

Q:为什么用户到边缘快了,整体就快了? 因为延迟主要由 RTT 与丢包决定。边缘把"跨运营商、跨地域的长肥管道"换成"同城短链路", TCP 慢启动、TLS 握手、丢包重传的代价都随之下降,收益远不止带宽。

小结

CDN = 调度 + 缓存 + 回源 + 传输优化。调度决定"去哪台",缓存决定"要不要回源", 而能否缓存由源站的 Cache-Control、验证器与 Vary 说了算。 工程上抓住三点:静态资源带哈希长缓存、入口 HTML 短缓存可刷新、用 X-Cache-Status 把命中率变成可观测指标。

笔记加载中…