3. 從上傳到存取:完整鏈路解析
3.1 檔案上傳的三種方式
方式一:用戶端 → 伺服器端 → 物件儲存(傳統模式)
瀏覽器 → 你的後端伺服器 → 物件儲存流程:
- 使用者選擇檔案,點擊上傳
- 檔案先上傳到你的後端伺服器
- 後端接收完整檔案後,再轉上傳到物件儲存
- 回傳上傳結果給使用者
優點:
- 實作簡單,前後端都好控制
- 可以在後端做檔案校驗、格式轉換
- 敏感操作可以記錄日誌、做權限校驗
缺點:
- 頻寬雙吃:使用者上傳佔用一次頻寬,伺服器轉傳又佔用一次
- 伺服器壓力大:大檔案會佔用大量記憶體和 CPU
- 上傳慢:相當於多了一道中轉,使用者感知到的上傳時間更長
適用場景:小檔案(<10MB)、需要後端處理(如圖片壓縮、加浮水印)、內部管理系統。
方式二:用戶端直傳物件儲存(現代推薦)
瀏覽器 ──────→ 物件儲存
↑
後端只簽發暫時憑證流程:
- 使用者選擇檔案,前端先向後端申請「上傳憑證」
- 後端驗證使用者身分,向物件儲存服務申請暫時 STS 憑證(帶過期時間)
- 後端把暫時憑證回傳給前端
- 前端拿著憑證,直接上傳檔案到物件儲存
- 物件儲存回傳上傳結果,前端通知後端「上傳完成」
優點:
- 上傳快:少了中轉環節,使用者感知速度最快
- 伺服器壓力小:只處理憑證簽發,不處理檔案串流
- 頻寬省:只走一次上傳流量
- 安全性高:暫時憑證有過期時間,洩露也危害有限
缺點:
- 實作稍複雜,需要理解 STS、簽章機制
- 前端需要處理分片上傳、斷點續傳等邏輯
- 跨域(CORS)需要設定
適用場景:大檔案上傳、使用者生成內容(UGC)、需要高並行上傳的業務。
方式三:分片上傳 + 斷點續傳(大檔案必備)
10GB 影片檔案
↓
切分成 1000 個 10MB 的分片
↓
並行上傳(同時傳 5 個分片)
↓
斷網了!已傳 600 個
↓
恢復網路,從第 601 個繼續傳
↓
所有分片傳完,發起「合併」請求為什麼需要分片?
| 場景 | 不分片 | 分片 |
|---|---|---|
| 網路波動 | 傳了 99% 斷網,全部重傳 | 只重傳失敗的分片 |
| 上傳速度 | 單執行緒,速度慢 | 多執行緒並行,速度快 |
| 記憶體佔用 | 需要快取整個檔案 | 只需快取目前分片 |
| 進度顯示 | 只有 0% 和 100% | 精確到每個分片的進度 |
主流雲端廠商的分片規格:
| 廠商 | 分片大小限制 | 最大分片數 | 最小分片大小 |
|---|---|---|---|
| 阿里雲 OSS | 100MB | 10000 | 100KB |
| 騰訊雲 COS | 5GB | 10000 | 1MB |
| AWS S3 | 5GB | 10000 | 5MB(推薦) |
| 七牛雲 | 100MB | 10000 | 4MB |
3.2 CDN 回源策略詳解
什麼是「回源」?
CDN 邊緣節點快取了來源站的內容,但當:
- 使用者請求的內容第一次被存取
- 快取的內容已過期(TTL 到期)
- 快取被手動清除/預熱
CDN 節點就需要向來源站請求最新內容,這個過程就叫「回源」。
回源的三種模式
| 模式 | 原理 | 適用場景 | 優缺點 |
|---|---|---|---|
| 直接回源 | CDN 節點 → 來源站 | 來源站有公網 IP,且流量不大 | 簡單直接,但來源站壓力大 |
| 中間源回源 | CDN 節點 → 中間層 → 來源站 | 大型網站,多層快取架構 | 分擔來源站壓力,架構複雜 |
| OSS/COS 作為來源站 | CDN 節點 → 物件儲存 | 靜態資源、圖片、影片 | 最佳實踐,成本低、效能好 |
回源設定實戰
場景 1:物件儲存作為來源站(推薦)
使用者存取:cdn.example.com/images/photo.jpg
↓
CDN 邊緣節點(台北)
↓
未命中,回源到來源站
↓
來源站:bucket-name.oss-cn-beijing.aliyuncs.com
↓
回傳圖片,CDN 快取並回應使用者關鍵設定項:
- 來源站類型:OSS/COS 網域名稱 或 自訂來源站
- 回源協定:HTTP 還是 HTTPS(建議 HTTPS)
- 回源 HOST:存取來源站時使用的 Host 標頭
- 回源 SNI:HTTPS 回源時的伺服器名稱指示
場景 2:多來源站負載平衡
當單個來源站扛不住回源壓力時,可以設定多個來源站:
CDN 邊緣節點
├─ 來源站 A (權重 50%)
├─ 來源站 B (權重 30%)
└─ 來源站 C (權重 20%)主備模式:
CDN 邊緣節點
├─ 主來源站 A (健康時全部流量)
└─ 備來源站 B (主來源故障時切換)回源頻寬 vs CDN 頻寬
這裡有個容易混淆的概念:
| 指標 | 定義 | 計費關係 |
|---|---|---|
| CDN 下行頻寬 | 從 CDN 節點到使用者的流量 | 通常按流量計費的 CDN 費用 |
| 回源頻寬 | 從來源站到 CDN 節點的流量 | 通常物件儲存或來源站出流量費用 |
省錢技巧:
- 提高 CDN 命中率(讓更多請求命中快取,減少回源)
- 設定合理的快取時間(TTL)
- 使用預熱功能,在使用者存取前就快取熱點內容
- 開啟「跟隨 301/302」,避免不必要的回源跳轉
3.3 快取策略設定
快取鍵(Cache Key):決定什麼算「同一個檔案」
CDN 如何判斷兩次請求是否應該回傳同一個快取副本?靠的就是快取鍵。
預設快取鍵通常包括:
- URL 路徑(不含查詢參數)
- 例如:
/images/photo.jpg
問題場景:
使用者 A 請求:/images/photo.jpg?w=100&h=100 (100x100 縮圖)
使用者 B 請求:/images/photo.jpg?w=800&h=600 (800x600 大圖)如果快取鍵只包含路徑,兩張不同尺寸的圖片會被認為是同一個檔案,導致混亂。
解決方案:自訂快取鍵規則
| 規則 | 範例 | 效果 |
|---|---|---|
| 保留指定查詢參數 | 保留 w、h | 不同尺寸分別快取 |
| 保留所有查詢參數 | 保留全部 | 完全精確匹配 |
| 忽略特定查詢參數 | 忽略 token、timestamp | 帶時間戳的 URL 能命中快取 |
| 包含請求標頭 | 包含 Accept-Language | 不同語言回傳不同內容 |
實戰設定範例(阿里雲 CDN):
快取鍵規則:
- URL 路徑:/images/*
- 保留查詢參數:w, h, format
- 忽略查詢參數:token, timestamp, utm_source快取時間(TTL):內容「新鮮度」的平衡
TTL(Time To Live)決定了內容在 CDN 節點上快取多久。設定太短,回源多、成本高;設定太長,內容更新後使用者看到舊內容。
按檔案類型設定 TTL 的建議:
| 檔案類型 | 建議 TTL | 原因 |
|---|---|---|
| HTML 頁面 | 0-5 分鐘 | 內容頻繁更新,需要即時 |
| JS/CSS 檔案 | 1 年(搭配檔名 hash) | 內容不變,檔名變化即快取失效 |
| 圖片/影片 | 7-30 天 | 更新頻率低,可長期快取 |
| 字型檔案 | 1 年 | 幾乎不變 |
| API 回應 | 0-5 分鐘(視業務) | 資料即時性要求高 |
前端工程化搭配 CDN 的最佳實踐:
javascript
// webpack/vite 設定
output: {
filename: 'js/[name]-[contenthash:8].js',
chunkFilename: 'js/[name]-[contenthash:8].chunk.js',
}產生的檔名:app-a3f2b1c9.js
- 檔案內容變化 → hash 變化 → 新 URL → 自然快取失效
- 檔案內容不變 → hash 不變 → URL 不變 → 長期快取命中
快取清除與預熱
手動清除(應急場景):
當你更新了來源站內容,但 CDN 快取還沒過期,使用者看到的還是舊內容:
| 清除類型 | 效果 | 耗時 | 適用場景 |
|---|---|---|---|
| URL 清除 | 指定 URL 的快取失效 | 5-10 分鐘 | 單個檔案更新 |
| 目錄清除 | 指定目錄下所有內容失效 | 10-30 分鐘 | 批量更新 |
| 全站清除 | 整個網域的快取全部失效 | 30 分鐘以上 | 緊急復原 |
重要提醒:清除只是讓快取失效,下次請求會回源拉取新內容。不要在高峰期大批量清除,否則可能導致來源站被打爆。
預熱( proactive 最佳化):
清除是被動的(內容已更新),預熱是主動的(提前快取)。
場景:明天上午 10 點要發一篇爆款文章
今晚就提交預熱請求:
- URL: https://cdn.example.com/articles/爆款文章.html
- 預熱範圍:全國所有邊緣節點
效果:
明天 10 點使用者存取時,內容已經在邊緣節點等著了
→ 零回源延遲,秒開體驗