| 方案 | 架構 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| 1. 客戶端直傳 C | Browser → Server C | 減輕 Web 節點壓力;簡單直接 | 需暴露 C 給公網;跨域複雜;認證傳遞困難 | 簡單業務、靜態資源為主 |
| 2. Web 節點轉發 | Browser → A/B → C | 統一認證授權;隱藏儲存層 | 雙倍頻寬消耗;Web 節點成瓶頸 | 中小型應用、需嚴格權限控制 |
| 3. 共享掛載(推薦) | A/B 掛載 C 的共享目錄 | 零轉發開銷;POSIX 語義;原生支援 | 單點故障;網路檔案系統效能 | 高效能、低延遲需求 |
| 4. 反向代理 + 統一上傳服務(最佳) | Browser → Nginx → Upload Service → C | 解耦上傳邏輯;水平擴展;統一限流熔斷 | 架構複雜度較高 | 大型分散式系統、微服務架構 |
# nginx.conf
upstream upload_backend {
least_conn;
server 10.0.1.10:8080 max_fails=3 fail_timeout=30s; # Upload Service 節點1
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s; # Upload Service 節點2
}
server {
listen 80;
server_name upload.example.com;
client_max_body_size 2G; # 支援大檔案
client_body_timeout 300s;
# 僅允許內網 Web 節點及授權 IP
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
location /upload {
proxy_pass https://upload_backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_request_buffering off; # 關鍵:禁用緩衝,支援流式上傳
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /files {
# 靜態檔案直接由 Nginx 服務(需掛載共享儲存)
alias /mnt/shared_storage/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
// 核心邏輯:驗證 → 流式寫入 → 返回訪問 URL
func UploadHandler(w http.ResponseWriter, r *http.Request) {
// 1. 驗證來源(JWT、API Key、mTLS 等)
if !validateSource(r) {
http.Error(w, "Unauthorized", 401)
return
}
// 2. 解析 multipart/form-data(流式,不載入記憶體)
reader, err := r.MultipartReader()
if err != nil { http.Error(w, err.Error(), 400); return }
for {
part, err := reader.NextPart()
if err == io.EOF { break }
if err != nil { http.Error(w, err.Error(), 500); return }
if part.FileName() == "" { continue } // 非檔案欄位
// 3. 生成唯一路徑:/year/month/day/uuid.ext
savePath := generateUniquePath(part.FileName())
fullPath := filepath.Join("/mnt/shared_storage", savePath)
// 確保目錄存在
os.MkdirAll(filepath.Dir(fullPath), 0755)
// 4. 流式寫入磁碟
dst, err := os.Create(fullPath)
if err != nil { http.Error(w, err.Error(), 500); return }
io.Copy(dst, part) // 零拷貝優化可用 syscall.Splice
dst.Close()
// 5. 返回可訪問 URL
json.NewEncoder(w).Encode(map[string]string{
"url": "https://cdn.example.com/files/" + savePath,
"path": savePath,
})
}
}
/mnt/shared_storage(NFS / CephFS / GlusterFS / S3FS)valid_referers + secure_link 模組# 兼容舊版直接上傳到 Web 節點的代碼
location /legacy_upload {
proxy_pass https://web_servers;
# 在 Web 節點內部調用上傳服務 API,對前端透明
}
Web 叢集檔案上傳的核心矛盾在於 **「有狀態檔案」與「無狀態計算」的解耦**。採用「Nginx 反向代理 + 專用上傳服務 + 共享分散式儲存」架構,將上傳邏輯從業務節點剝離,實現水平擴展、統一治理、高效能服務,是成熟的企業級解決方案。