首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Web 叢集架構下的檔案上傳最佳實踐:共享儲存與反向代理解決方案

     編輯:程式設計綜合問答

架構需求分析

  • Web 伺服器 A、B 需共享上傳檔案
  • 檔案實體儲存於儲存伺服器 C
  • 安全性:僅 A、B 及通過認證的客戶端可上傳
  • Web 節點需直接讀取/服務檔案(圖片、視頻等)

方案對比

方案架構優點缺點適用場景
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 反向代理 + 專用上傳服務

1. Nginx 配置(前端入口)

# 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";
    }
}

2. 專用上傳服務(Go/Node.js/Java)

// 核心邏輯:驗證 → 流式寫入 → 返回訪問 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,
        })
    }
}

3. 儲存伺服器 C 配置

  • 掛載點:/mnt/shared_storage(NFS / CephFS / GlusterFS / S3FS)
  • 網路:萬兆內網,獨立 VLAN
  • 備份:快照 + 異地複製
  • 監控:磁碟 I/O、容量、Inode 使用率

安全強化措施

  1. 簽名直傳:Web 節點預簽名 URL,客戶端直傳儲存服務,繞過 Web 節點
  2. 防盜鏈:Nginx valid_referers + secure_link 模組
  3. 病毒掃描:上傳完成觸發異步掃描(ClamAV),通過才對外可見
  4. 配額限制:用戶級/租戶級儲存配額與單檔大小限制

遷移舊系統的兼容策略

# 兼容舊版直接上傳到 Web 節點的代碼
location /legacy_upload {
    proxy_pass https://web_servers;
    # 在 Web 節點內部調用上傳服務 API,對前端透明
}

總結

Web 叢集檔案上傳的核心矛盾在於 **「有狀態檔案」與「無狀態計算」的解耦**。採用「Nginx 反向代理 + 專用上傳服務 + 共享分散式儲存」架構,將上傳邏輯從業務節點剝離,實現水平擴展、統一治理、高效能服務,是成熟的企業級解決方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved