7. 實戰案例:從 0 搭建圖片加速方案
7.1 業務場景
假設你是一個圖片社群的技術負責人,面臨以下挑戰:
- 使用者上傳:使用者每天上傳 100 萬張圖片(平均 2MB/張)
- 使用者存取:每天 5000 萬次圖片檢視請求
- 存取分佈:使用者遍佈全國,海外也有少量存取
- 效能要求:圖片載入時間 < 500ms
- 成本預算:盡量控制在每月 5 萬以內
7.2 架構設計
┌──────────────────────────────────────┐
│ 使用者上傳流程 │
└──────────────────────────────────────┘
使用者瀏覽器 後端服務 物件儲存
│ │ │
│ 1. 申請上傳憑證 │ │
│───────────────────────────────────────────>│ │
│ │ │
│ │ 2. 申請 STS 暫時憑證 │
│ │───────────────────────────>│
│ │ │
│ │ 3. 回傳 STS 憑證 │
│ │<───────────────────────────│
│ │ │
│ 4. 回傳上傳憑證(含 STS) │
│<───────────────────────────────────────────│ │
│ │ │
│ 5. 直接上傳檔案(使用 STS 簽章) │
│──────────────────────────────────────────────────────────────────────>│
│ │ │
│ 6. 回傳上傳結果(URL、ETag 等) │
│<──────────────────────────────────────────────────────────────────────│
│ │ │
│ 7. 通知後端上傳完成(儲存到資料庫) │
│───────────────────────────────────────────>│ │
┌──────────────────────────────────────┐
│ 使用者存取流程 │
└──────────────────────────────────────┘
使用者瀏覽器 DNS 解析 CDN 節點 物件儲存(來源站)
│ │ │ │
│ 1. 請求圖片 URL │ │ │
│────────────────────────────────────────>│ │
│ │ │ │
│ │ 2. DNS 查詢 │ │
│ │────────────────────>│ │
│ │ │ │
│ │ 3. 回傳最優節點 IP │ │
│ │<────────────────────│ │
│ │ │ │
│ 4. 連線 CDN 節點 │ │ │
│────────────────────────────────────────>│ │
│ │ │ │
│ │ 5. 檢查快取 │ │
│ │ ├─ 命中?直接回傳 │
│ │ └─ 未命中?繼續 │
│ │ │ │
│ │ │ 6. 回源獲取 │
│ │ │──────────────────>│
│ │ │ │
│ │ │ 7. 回傳檔案 │
│ │ │<──────────────────│
│ │ │ │
│ │ 8. 快取並回應 │ │
│<────────────────────────────────────────│ │7.3 關鍵設定詳解
物件儲存設定
儲存貯體規劃:
Bucket: myapp-images-prod
├─ 目錄結構:
│ ├─ uploads/ # 使用者上傳的原圖
│ │ ├─ 2024/01/15/user123-abc.jpg
│ │ └─ 2024/01/15/user456-def.png
│ ├─ thumbnails/ # 縮圖
│ │ ├─ small/ # 100x100
│ │ ├─ medium/ # 400x300
│ │ └─ large/ # 800x600
│ └─ processed/ # 處理後的圖片(加浮水印等)
│
├─ 存取權限:
│ ├─ 原圖目錄:私有(需簽章存取)
│ ├─ 縮圖目錄:公共讀
│ └─ 跨域 CORS:允許 *.myapp.com 存取
│
└─ 生命週期政策:
├─ 上傳 7 天後:低頻儲存(省 40% 費用)
├─ 上傳 90 天後:歸檔儲存(省 70% 費用)
└─ 上傳 3 年後:自動刪除(或轉存到更便宜的冷儲存)CORS 跨域設定:
xml
<AllowedOrigin>https://myapp.com</AllowedOrigin>
<AllowedOrigin>https://www.myapp.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
<ExposeHeader>x-oss-request-id</ExposeHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>CDN 加速設定
快取策略設定:
全域預設規則:
├─ 快取鍵:URL 路徑 + 保留 w、h、format 查詢參數
├─ 預設 TTL:7 天
└─ 回源 HOST:自動跟隨
按檔案類型細分:
├─ *.html:
│ ├─ TTL:5 分鐘
│ └─ 優先從記憶體快取讀取
│
├─ *.js, *.css:
│ ├─ TTL:1 年
│ └─ 忽略查詢參數(因為檔名有 hash)
│
├─ *.jpg, *.png, *.gif, *.webp:
│ ├─ TTL:30 天
│ ├─ 保留查詢參數(w、h、format 用於動態裁剪)
│ └─ 啟用圖片自動壓縮最佳化
│
└─ /api/*:
├─ TTL:0(不快取)
└─ 直接回源HTTPS 最佳化設定:
憑證設定:
├─ 憑證類型:泛網域憑證 *.myapp.com
├─ 部署方式:CDN 主控台上傳,自動續期
└─ 備用憑證:EV 憑證用於主網域(顯示綠色網址列)
TLS 設定:
├─ 最低 TLS 版本:1.2(相容性與安全平衡)
├─ 最高 TLS 版本:1.3
├─ 密碼套件:僅啟用強加密套件
├─ OCSP Stapling:開啟
├─ TLS 工作階段重用:開啟 Session Ticket
└─ HSTS:開啟(max-age=31536000)
HTTP/2 與 HTTP/3:
├─ HTTP/2:開啟(多工、標頭壓縮)
├─ HTTP/2 Server Push:按需開啟(推薦用 Preload 替代)
└─ HTTP/3 (QUIC):開啟(實驗性功能,逐步放量)7.4 成本控制策略
費用構成分析
月度 CDN + 物件儲存費用構成:
CDN 部分:
├─ 下行流量費(大頭,約 60%)
│ ├─ 中國大陸:0.15-0.30 元/GB
│ ├─ 亞太地區:0.40-0.80 元/GB
│ └─ 歐美:0.30-0.60 元/GB
│
├─ 請求數費用(小頭,約 5%)
│ ├─ HTTP:0.01-0.05 元/萬次
│ └─ HTTPS:0.05-0.15 元/萬次(因為 TLS 交握消耗資源)
│
├─ 頻寬峰值費用(可選計費方式)
│ └─ 95 峰值計費:適合流量波動大的場景
│
└─ 加值功能費(約 5%)
├─ HTTPS 憑證管理
├─ WAF 防護
├─ 即時日誌推送
└─ 邊緣指令碼/函式
物件儲存部分:
├─ 儲存容量費(約 15%)
│ ├─ 標準儲存:0.12-0.15 元/GB/月
│ ├─ 低頻儲存:0.08-0.10 元/GB/月
│ └─ 歸檔儲存:0.03-0.05 元/GB/月
│
├─ 請求費用(約 5%)
│ ├─ PUT:0.01-0.05 元/萬次
│ └─ GET:0.005-0.01 元/萬次
│
├─ 資料取回費用(低頻/歸檔)
│ └─ 提前刪除或取回收取額外費用
│
└─ 回源出流量費(約 10%)
└─ CDN 回源到物件儲存的流量費省錢技巧實戰
技巧 1:儲存分級,自動生命週期管理
yaml
# 生命週期規則範例
rules:
- id: image-lifecycle
prefix: uploads/
transitions:
# 7 天後轉低頻儲存,省 30% 費用
- days: 7
storageClass: IA
# 90 天後轉歸檔儲存,省 70% 費用
- days: 90
storageClass: Archive
# 3 年後自動刪除
expiration:
days: 1095技巧 2:提高 CDN 命中率,減少回源
命中率從 90% 提升到 95% 意味著什麼?
假設:
- 日流量:10 TB
- 命中率 90%:回源 1 TB
- 命中率 95%:回源 0.5 TB
節省回源流量:0.5 TB/天 × 0.15 元/GB × 30 天 = 2250 元/月技巧 3:壓縮與格式最佳化
圖片最佳化方案:
├─ 原圖儲存在物件儲存(不對外直接開放)
├─ CDN 開啟圖片處理功能:
│ ├─ 格式自動轉換:JPEG → WebP/AVIF(省 30-50%)
│ ├─ 品質自動壓縮:視覺無損壓縮(省 20-40%)
│ ├─ 尺寸自適應:根據裝置回傳合適尺寸
│ └─ 漸進式載入:先模糊後清晰
└─ 效果:頻寬成本降低 50-70%技巧 4:頻寬峰值上限與警報
yaml
# 頻寬上限設定
bandwidth_cap:
daily_limit: 500 # Mbps,日峰值超過則自動停用 CDN
monthly_limit: 10000 # GB,月流量超過則停用
# 警報閾值
alerts:
- threshold: 70% # 達到 70% 發警報
channels: [sms, email]
- threshold: 90% # 達到 90% 打電話
channels: [phone]