跳至主要內容
Skip to content

CDN 與邊緣快取:加速全球訪問

CDN(Content Delivery Network,內容傳遞網路)是現代 Web 性能優化的基石。本篇將深入探討 CDN 的運作原理與實戰配置。


一、 什麼是 CDN?

1.1 問題:地理延遲

物理距離造成延遲,即使頻寬再大也無法解決。

1.2 解決方案:邊緣節點

1.3 CDN 的價值

優勢說明
降低延遲就近存取
減少負載分散請求
高可用性多點部署
DDoS 防護邊緣過濾
節省成本減少頻寬

二、 CDN 運作原理

2.1 首次請求

2.2 後續請求

2.3 快取過期


三、 CDN 快取配置

3.1 遵循 Origin 標頭

CDN 會遵循原始伺服器的 Cache-Control:

javascript
// 原始伺服器
app.use("/assets", (req, res, next) => {
  res.set("Cache-Control", "public, max-age=86400, s-maxage=604800");
  next();
});
// s-maxage: CDN 快取 7 天
// max-age: 瀏覽器快取 1 天

3.2 CDN 規則覆蓋

大多數 CDN 允許設定規則覆蓋:

yaml
# Cloudflare 頁面規則
- url: "*.example.com/assets/*"
  settings:
    browser_ttl: 86400
    edge_ttl: 604800
    cache_level: cache_everything

3.3 快取 Key

快取以什麼作為識別:

# 預設:URL
https://example.com/api/data

# 可包含:
# - 查詢參數
# - Cookie
# - 標頭
# - 地理位置
javascript
// 設定 Vary 影響快取 Key
app.get("/api/content", (req, res) => {
  res.set("Vary", "Accept-Language");
  // ...
});

四、 快取失效(Purge)

4.1 為什麼需要 Purge?

  • 內容更新需要立即生效
  • 發現錯誤需要緊急修正
  • 快取還沒過期但必須更新

4.2 Purge 方式

方式說明使用場景
單一 URL清除特定檔案個別更新
前綴 (Prefix)清除路徑下所有批量更新
標籤 (Tag)清除相關資源精確控制
全部 (Purge All)清除所有快取緊急情況

4.3 API 範例

javascript
// Cloudflare Purge API
async function purgeUrls(urls) {
  const response = await fetch(
    `https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${API_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ files: urls }),
    }
  );
  return response.json();
}

// 使用
await purgeUrls([
  "https://example.com/image.jpg",
  "https://example.com/style.css",
]);

4.4 標籤 Purge

javascript
// 設定標籤
app.get("/api/posts/:id", async (req, res) => {
  const post = await Post.findById(req.params.id);

  res.set("Cache-Tag", `post-${post.id}, author-${post.authorId}`);
  res.json(post);
});

// 當作者更新時,清除所有相關文章
async function purgeByAuthor(authorId) {
  await cloudflare.purgeByTag([`author-${authorId}`]);
}

五、 主流 CDN 比較

5.1 服務商一覽

CDN特點適用場景
Cloudflare免費方案、DDoS 防護通用
AWS CloudFrontAWS 整合、Lambda@EdgeAWS 生態
Fastly即時 Purge、VCL高度客製
Akamai全球最大網路企業級
Bunny CDN價格便宜預算有限

5.2 定價模式

模式說明
頻寬計費按傳輸量
請求計費按請求數
混合計費兩者結合

六、 Cloudflare 配置

6.1 基本設定

bash
# 1. 註冊並添加網站
# 2. 更改 DNS 為 Cloudflare
# 3. 配置快取規則

6.2 頁面規則

yaml
# 靜態資源:積極快取
- url: "example.com/assets/*"
  settings:
    cache_level: cache_everything
    edge_ttl: 2592000 # 30 天
    browser_ttl: 86400 # 1 天

# API:根據回應標頭
- url: "example.com/api/*"
  settings:
    cache_level: standard
    origin_cache_control: on

# 管理後台:不快取
- url: "admin.example.com/*"
  settings:
    cache_level: bypass
    security_level: high

6.3 Workers(邊緣運算)

javascript
// Cloudflare Worker
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);

  // 自訂快取邏輯
  if (url.pathname.startsWith("/api/")) {
    const cacheKey = new Request(url.toString(), request);
    const cache = caches.default;

    let response = await cache.match(cacheKey);

    if (!response) {
      response = await fetch(request);

      // 只快取成功回應
      if (response.ok) {
        const cached = response.clone();
        cached.headers.set("Cache-Control", "max-age=60");
        event.waitUntil(cache.put(cacheKey, cached));
      }
    }

    return response;
  }

  return fetch(request);
}

七、 AWS CloudFront 配置

7.1 建立分發

javascript
// AWS CDK
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";

const distribution = new cloudfront.Distribution(this, "Dist", {
  defaultBehavior: {
    origin: new origins.S3Origin(bucket),
    cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
    viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
  },
  additionalBehaviors: {
    "/api/*": {
      origin: new origins.HttpOrigin("api.example.com"),
      cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
    },
  },
});

7.2 失效(Invalidation)

bash
aws cloudfront create-invalidation \
  --distribution-id EDFDVBD632BHDS5 \
  --paths "/images/*" "/css/*"

八、 最佳實踐

8.1 靜態資源策略

1. 使用內容雜湊命名:app.a1b2c3.js
2. 設定長期快取:max-age=1y
3. HTML 不快取或短期快取
4. 使用版本化部署

8.2 API 快取策略

javascript
// 公開、變化慢的資料
res.set("Cache-Control", "public, s-maxage=300");

// 私有資料
res.set("Cache-Control", "private, no-store");

// 使用 stale-while-revalidate
res.set("Cache-Control", "public, s-maxage=60, stale-while-revalidate=86400");

8.3 監控快取效能

關注的指標:

  • 命中率:快取命中次數 / 總請求數
  • 回源頻寬:從 Origin 拉取的資料量
  • TTFB:首位元組時間

總結

概念說明
CDN分散式內容傳遞
邊緣節點靠近用戶的快取伺服器
s-maxage共享快取專用
Purge主動清除快取
Cache Tag精確失效控制
邊緣運算Workers/Lambda@Edge

> **選擇 CDN 的考量**:

  • 節點覆蓋範圍
  • Purge 速度
  • 定價模式
  • 功能豐富度
  • 技術支援

進階挑戰

  1. 設計一個自動化的快取失效系統,當 CMS(Content Management System,內容管理系統)更新內容時自動 Purge。
  2. 使用 Cloudflare Workers 實作一個 A/B 測試系統。
  3. 比較不同 CDN 在你的目標地區的效能表現。

延伸閱讀與資源