全部產品
Search
文件中心

Object Storage Service:OSS在內網環境中如何?百Gbps頻寬

更新時間:Mar 27, 2025

目前,OSS在上海、深圳、北京和杭州地區已全面支援單帳號內網頻寬最高可達100 Gbps。本文將深入探討如何充分發揮OSS的百Gbps頻寬效能,包括關鍵要點分析,以及通過Go語言實現檔案下載並測試峰值頻寬的實踐案例。最後,還將介紹如何利用常用工具通過並發下載提升OSS的下載效能。

適用情境

在Object Storage Service的應用情境中,超過100 Gbps頻寬的需求通常出現在需要處理海量資料、支援高並發訪問或對即時性要求極高的特殊業務情境中。例如

  • 巨量資料分析與計算:資料規模大,單次任務可能需要讀取TB級甚至PB級的資料,且即時性要求高,為提高計算效率,資料讀取速度必須足夠快,避免成為瓶頸。

  • AI訓練資料集載入:資料規模大,訓練資料集可能達到PB層級,有高輸送量需求,多個訓練節點同時載入資料,總頻寬需求可能達到百Gbps。

  • 備份與恢複:資料規模大,備份和恢複操作涉及PB級資料,例如全量備份,若規定在有限時間內完成備份和恢複操作,為滿足時間要求,備份和恢複的頻寬需求可能達到百Gbps。

  • 高效能科學計算:資料規模大,科學計算任務通常需要處理PB級甚至更大的資料集,多個研究團隊可能同時訪問同一份資料,從而產生高並發訪問和高頻寬需求。為了支援即時分析和團隊協作,確保資料轉送速度至關重要。

要點分析

要實現百Gbps寬頻,首先需要選擇合適ECS執行個體規格確保頻寬上限,其次,若涉及落盤操作,應選用高效能磁碟以提升效率。此外,訪問資料時建議通過VPC內網,以提高訪問速度,並在需要並發下載時,採用相應的最佳化技巧,以充分釋放下載頻寬的潛力。

網路接收能力

將OSS的用戶端安裝於ECS上時,資料下載速度會受ECS網路速度的制約。在阿里雲平台,當前網路能力最強的機型已能提供160 Gbps的頻寬。採用多機叢集模式時,在客戶側進行並發訪問的情況下,其總頻寬能夠達到100 Gbps;而在單機情形下,則優先選用大頻寬的網路增強型或者高主頻型(高主頻在接收大量資料包時具備速度優勢)。

說明

需注意基於目前ECS的規格,單個彈性網卡最大支援100 Gbps的頻寬。根據ECS的規則,單機頻寬超過100 Gbps時需要掛載多個彈性網卡,具體操作請參見彈性網卡

磁碟IO

資料下載至本地後,若執行資料落盤操作,下載速度便會受磁碟效能所限。例如ossutil、ossfs等工具在預設設定下均存在資料落盤行為,此時可考慮選用更高效能的磁碟或者記憶體盤來改善狀況,如圖所示。

說明

儘管阿里雲ESSD雲端硬碟已可實現32 Gbps的單盤輸送量,然而與記憶體相比,仍存在顯著差距。為實現最大下載頻寬,應盡量避免資料落盤操作。有關ossfs如何避免資料落盤,提高讀取效能,請參見唯讀情境效能調優

image

使用VPC網路

阿里雲內網針對網路資料請求進行了最佳化,在使用VPC內網網域名稱時,能夠擷取比公網更穩定的網路服務。若要達到最大頻寬,需採用VPC內網網路服務。

客戶的ECS運行於客戶的VPC網路之中,OSS提供了可供任意客戶VPC訪問的統一內網網域名稱(例如:oss-cn-beijing-internal.aliyuncs.com)。ECS與OSS之間的資料流會經過SLB負載平衡,請求被發送至後端的分布式叢集裡,從而將資料請求的壓力均勻分散到整個叢集,使OSS具備了強大的高並發處理能力。

並發下載

OSS採用HTTP協議傳輸資料,鑒於單個HTTP請求的效能存在局限,對OSS實施資料下載加速的一項基本策略為並發下載。即把一個檔案分割成多個range,讓每個請求僅訪問其中一個range,通過這種方式來擷取最大的下載頻寬。由於OSS依據API調用次數計費,所以並非將檔案切分得越細小越好。range越小,API調用次數就會越多,並且更小的range其單流下載速度也無法達到峰值。有關常用工具的並發下載技巧,請參見常用工具並發下載技巧

實踐案例

為了測試最大頻寬的下載能力,我們專門構建了一個Go語言測試程式,用於從OSS下載一個100 GB大小的二進位bin檔案。在該程式的設計中,我們採用了特殊的資料處理策略,資料不進行落盤操作,即資料讀取一遍後便直接丟棄。同時,將大檔案的讀取過程拆分成多個range,並且把range的大小以及並發資料量設定為可調節的參數,這樣就能方便地通過調整這些參數來實現最大頻寬的下載效果。具體的實驗過程如下。

實驗環境

執行個體規格

vCPU

記憶體(GiB)

網路頻寬基礎/突發(Gbit/s)

網路收發包PPS

串連數

多隊列

彈性網卡

單網卡私人IPv4/IPv6地址數

可掛載的雲端硬碟數

雲端硬碟IOPS基礎/突發

雲端硬碟頻寬基礎/突發(Gbit/s)

ecs.hfg8i.32xlarge

128

512

100/無

3000 萬

400 萬

64

15

50/50

64

90萬/無

64/無

測試步驟

  1. 配置環境變數。

    export OSS_ACCESS_KEY_ID=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    export OSS_ACCESS_KEY_SECRET=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
  2. 程式碼範例。

    package main
    
    import (
        "context"
        "flag"
        "fmt"
        "io"
        "log"
        "time"
        "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
        "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
    )
    
    // 定義全域變數,用於儲存命令列參數
    var (
        region      string // OSS 儲存桶所在的地區
        endpoint    string // OSS 服務的訪問網域名稱
        bucketName  string // OSS 儲存桶的名稱
        objectName  string // OSS 對象的名稱
        chunkSize   int64  // 分塊大小(位元組)
        prefetchNum int    // 預取數量
    )
    
    // 初始化函數,用於解析命令列參數
    func init() {
        flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
        flag.StringVar(&endpoint, "endpoint", "", "The domain names that other services can use to access OSS.")
        flag.StringVar(&bucketName, "bucket", "", "The `name` of the bucket.")
        flag.StringVar(&objectName, "object", "", "The `name` of the object.")
        flag.Int64Var(&chunkSize, "chunk-size", 0, "The chunk size, in bytes")
        flag.IntVar(&prefetchNum, "prefetch-num", 0, "The prefetch number")
    }
    
    func main() {
        // 解析命令列參數
        flag.Parse()
    
        // 檢查必要的參數是否提供
        if len(bucketName) == 0 {
            flag.PrintDefaults()
            log.Fatalf("invalid parameters, bucket name required")
        }
    
        if len(region) == 0 {
            flag.PrintDefaults()
            log.Fatalf("invalid parameters, region required")
        }
    
        // 配置 OSS 用戶端
        cfg := oss.LoadDefaultConfig().
            WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). // 使用環境變數中的憑證
            WithRegion(region) // 設定地區
    
        // 如果提供了自訂 endpoint,則設定
        if len(endpoint) > 0 {
            cfg.WithEndpoint(endpoint)
        }
    
        // 建立 OSS 用戶端
        client := oss.NewClient(cfg)
    
        // 開啟 OSS 檔案
        f, err := client.OpenFile(context.TODO(), bucketName, objectName, func(oo *oss.OpenOptions) {
            oo.EnablePrefetch = true      // 啟用預取
            oo.ChunkSize = chunkSize      // 設定分塊大小
            oo.PrefetchNum = prefetchNum  // 設定預取數量
            oo.PrefetchThreshold = int64(0) // 設定預取閾值
        })
    
        if err != nil {
            log.Fatalf("open fail, err:%v", err)
        }
    
        // 記錄開始時間
        startTick := time.Now().UnixNano() / 1000 / 1000
    
        // 將檔案內容讀取並丟棄(用於測試讀取速度)
        written, err := io.Copy(io.Discard, f)
    
        // 記錄結束時間
        endTick := time.Now().UnixNano() / 1000 / 1000
    
        if err != nil {
            log.Fatalf("copy fail, err:%v", err)
        }
    
        // 計算讀取速度(MiB/s)
        speed := float64(written/1024/1024) / float64((endTick-startTick)/1000)
    
        // 輸出平均讀取速度
        fmt.Printf("average speed:%.2f(MiB/s)\n", speed)
    }
  3. 啟動測試程式。

    go run down_object.go -bucket yourbucket -endpoint oss-cn-hangzhou-internal.aliyuncs.com  -object 100GB.file -region cn-hangzhou -chunk-size 419430400 -prefetch-num 256

測試結論

在測試實際下載耗時的過程中,我們通過調整並發度和chunk大小來觀察資料變化。一般來說,並發度設定為core的1-4倍較為合適,chunk大小則盡量與FileSize/Concurrency的值保持一致,且不能小於2 MB。按照這樣的參數設定,最終獲得了最短的下載耗時,測試中的峰值速度達到了100 Gbps。

序號

Concurrency(並發數)

blcokSize(塊大小:MB)

峰值頻寬(Gbps)

e2e(端到端時間:s)

1

128

800

100

16.321

2

256

400

100

14.881

3

512

200

100

15.349

4

1024

100

100

19.129

常用工具並發下載技巧

以下為您介紹常用工具在最佳化Object Storage Service下載效能方面的具體方法與應用策略。

ossutil

  • 參數說明

    選項名稱

    描述

    --bigfile-threshold

    開啟大檔案斷點續傳的檔案大小閾值,單位為Byte,預設值為100 MByte,取值範圍為0~9223372036854775807。

    --range

    下載檔案時,可以指定檔案內容的位元組範圍進行下載,位元組從0開始編號。

    • 可以指定一個區間,例如3-9表示從第3個位元組到第9個位元組(包含第3和第9位元組)。

    • 可以指定從什麼欄位開始,例如3-表示從第3個位元組開始到檔案結尾(包含第3個位元組)。

    • 可以指定從什麼欄位結束,例如-9表示從0位元組到第9個位元組(包含第9個位元組)。

    --parallel

    單檔案內部操作的並發任務數,取值範圍為1~10000,預設由ossutil根據操作類型和檔案大小自行決定。

    --part-size

    分區大小以位元組為單位,合適的取值範圍是2097152-16777216 B,也就是 2-16 MB。一般來說,當CPU核心數量較多時,可將分區大小設定得小一些;而當CPU核心數量較少時,則可適當調高分區大小。

  • 參考樣本

    以下命令用於採用256並發處理以及468435456位元組的分塊策略,將目標Bucket中100GB.file檔案下載到本地/dev/shm目錄,並統計耗時。

    time ossutil --parallel=256 --part-size=468435456 --endpoint=oss-cn-hangzhou-internal.aliyuncs.com cp oss://cache-test/EcsTest/100GB.file /dev/shm/100GB.file
  • 效能說明

    端到端平均速度為2.94GB/s(約24 Gbps)。

    image

ossfs

  • 參數說明

    選項名稱

    描述

    parallel_count

    以分區模式上傳大檔案時,分區的並發數,預設值為5。

    multipart_size

    以分區模式上傳資料時分區的大小,單位是MB,預設值為10。該參數會影響最大支援的檔案大小。分區模式上傳時,最多的分區數為10000,預設值下,最大支援的檔案為100 GB。如果需要支援更大的檔案,需要根據需求調整這個值。

    direct_read

    預設情況下ossfs會使用磁碟空間來儲存上傳或下載的臨時資料。您可以通過設定該選項來直接從OSS讀取資料而不使用本地磁碟空間。預設不設定,您可以使用-odirect_read來開啟直讀模式。

    說明

    當檔案在直讀過程中檢測到用write、rename或truncate操作時,該檔案會退出直讀模式直至檔案重新被開啟。

    direct_read_prefetch_chunks

    直讀模式下指定預讀到記憶體中chunk的數量,用來提升ossfs在順序讀情境下的效能,預設值是32。

    該選項僅在開啟直讀模式,即使用-odirect_read選項時生效。

    direct_read_chunk_size

    直讀模式下指定一次讀請求從OSS中讀取的資料量大小,單位為MB,預設值是4。取值範圍為1~32。

    該選項僅在開啟直讀模式,即使用-odirect_read選項時生效。

    ensure_diskfree

    控制預留磁碟空間大小。預設不預留。您可以通過該選項設定保留的可用硬碟空間大小,避免磁碟寫滿影響其他應用寫入,單位為MB。

    例如,您需要設定ossfs保留1024 MB的可用磁碟空間,則可以在掛載時添加-oensure_diskfree=1024

    free_space_ratio

    控制使用緩衝後的磁碟最小剩餘空間比例。例如,當磁碟空間為50GB時,如果配置為-o free_space_ratio=20,則保留50GB * 20% = 10 GB的空間。

    max_stat_cache_size

    用於指定檔案中繼資料的緩衝空間可緩衝多少個檔案的中繼資料。單位為個,預設值為100,000。當目錄下檔案比較多時,可以調整這個參數,加快ls的速度。如果要禁止使用中繼資料快取,可以設定為0。

    stat_cache_expire

    指定檔案中繼資料快取的失效時間,單位為秒,預設值為900秒。

    readdir_optimize

    控制是否使用緩衝最佳化,預設為不使用。

    添加該掛載選項後ossfs在ls時不會發送HeadObject請求去擷取檔案項中繼資料如giduid等,只有訪問檔案大小為0才發送HeadObject請求。不過,由於許可權檢查等原因,仍然可能產生一定數量的HeadObject請求,此參數請根據應用程式特性選擇。如需啟用,您可以在掛載時添加-oreaddir_optimize

  • 參考樣本

    說明

    具體參數大小請根據CPU處理能力和網路頻寬逐步進行調整,不建議設定過大。

    • 預設模式:掛載名為cache-test的bucket到本地/mnt/cache-test檔案夾下,並設定分區並發數為128,每個分區大小32 MB。

      ossfs cache-test /mnt/cache-test -ourl=http://oss-cn-hangzhou-internal.aliyuncs.com  -oparallel_count=128 -omultipart_size=32 
    • 直讀模式:掛載名為cache-test的bucket到本地/mnt/cache-test檔案夾下,同時開啟直讀模式,設定預取chunk數量為128,每個chunk大小32 MB。

      ossfs cache-test /mnt/cache-test -ourl=http://oss-cn-hangzhou-internal.aliyuncs.com  -odirect_read -odirect_read_prefetch_chunks=128 -odirect_read_chunk_size=32
  • 效能說明

    預設模式中資料會進行落盤。直讀模式資料儲存在記憶體中,訪問效果更高,但是記憶體開銷更大。

    說明

    在直讀模式下,ossfs以chunk為單位管理下載資料,預設chunk大小為4 MB,可通過direct_read_chunk_size參數自行設定。ossfs會在記憶體中保留 [當前 chunk - 1, 當前 chunk + direct_read_prefetch_chunks] 區間內的資料。判斷是否適合採用直讀模式,可依據記憶體大小,尤其是pagecache空間來確定。一般來說,當pagecache不夠大時更適合直讀模式。比如,機器總記憶體為16 GB,pagecache可以使用6 GB,那麼直讀模式適合6 GB以上的檔案。有關直讀模式詳細介紹,請參見直讀模式

    模式

    Concurrency(並發數)

    blcokSize(塊大小:MB)

    峰值頻寬(Gbps)

    e2e 頻寬(Gbps)

    e2e 耗時(s)

    預設

    128

    32

    24

    11.3

    72.01

    直讀

    128

    32

    24

    16.1

    50.9

    針對模型讀取的最佳化:

    模型大小(GB)

    預設模式(耗時:s,限制記憶體6 GB)

    混合直讀模式(耗時:s)

    混合直讀模式(耗時:s,調整chunk保留視窗[-32, +32])

    1

    8.19

    8.20

    8.56

    2.4

    24.5

    20.43

    20.02

    5

    26.5

    22.3

    19.89

    5.5

    22.8

    23.1

    22.98

    8.5

    106.0

    36.6

    36.00

    12.6

    154.6

    42.1

    41.9

Python SDK

在AI模型訓練情境裡,Python SDK預設是以串列方式訪問後端儲存服務的。 通過Python的並發庫進行多線程改造,頻寬獲得了極為顯著的提升。

  • 實驗情境

    測試選用的模型檔案大小約為5.6 GB,測試機器的規格為ECS48vCPU、具備16 Gbps頻寬以及180 GB記憶體。

  • 測試樣本

    import oss2
    import time
    import os
    import threading
    from io import BytesIO
    
    # 配置參數(通過環境變數擷取)
    OSS_CONFIG = {
        "bucket_endpoint": os.environ.get('OSS_BUCKET_ENDPOINT', 'oss-cn-hangzhou-internal.aliyuncs.com'),  # 預設Endpoint樣本
        "bucket_name": os.environ.get('OSS_BUCKET_NAME', 'bucket_name'),  #Bucket 名稱
        "access_key_id": os.environ['ACCESS_KEY_ID'],         # RAM使用者ACCESS_KEY_ID
        "access_key_secret": os.environ['ACCESS_KEY_SECRET']  # RAM使用者ACCESS_KEY_SECRET
    }
    
    # 初始化 OSS Bucket 對象
    def __bucket__():
        auth = oss2.Auth(OSS_CONFIG["access_key_id"], OSS_CONFIG["access_key_secret"])
        return oss2.Bucket(
            auth, 
            OSS_CONFIG["bucket_endpoint"], 
            OSS_CONFIG["bucket_name"], 
            enable_crc=False
        )
    
    # 擷取對象大小
    def __get_object_size(object_name):
        simplifiedmeta = __bucket__().get_object_meta(object_name)
        return int(simplifiedmeta.headers['Content-Length'])
    
    # 擷取遠程模型最後修改時間
    def get_remote_model_mmtime(model_name):
        return __bucket__().head_object(model_name).last_modified
    
    # 列出遠程模型檔案
    def list_remote_models(ext_filter=('.ckpt',)):  # 添加預設副檔名過濾
        dir_prefix = ""
        output = []
        
        for obj in oss2.ObjectIteratorV2(
            __bucket__(),
            prefix=dir_prefix,
            delimiter='/',
            start_after=dir_prefix,
            fetch_owner=False
        ):
            if not obj.is_prefix():
                _, ext = os.path.splitext(obj.key)
                if ext.lower() in ext_filter:
                    output.append(obj.key)
        return output
    
    # 分段下載線程函數
    def __range_get(object_name, buffer, offset, start, end, read_chunk_size, progress_callback, total_bytes):
        chunk_size = int(read_chunk_size)
        with __bucket__().get_object(object_name, byte_range=(start, end)) as object_stream:
            s = start
            while True:
                chunk = object_stream.read(chunk_size)
                if not chunk:
                    break
                buffer.seek(s - offset)
                buffer.write(chunk)
                s += len(chunk)
                # 計算已下載位元組數並調用進度回調
                if progress_callback:
                    progress_callback(s - start, total_bytes)
    
    # 讀取遠程模型(增加進度回調選擇性參數)
    def read_remote_model(
        checkpoint_file, 
        start=0, 
        size=-1, 
        read_chunk_size=2*1024*1024,  # 2MB
        part_size=256*1024*1024,      # 256MB
        progress_callback=None        # 進度回調
    ):
        time_start = time.time()
        buffer = BytesIO()
        obj_size = __get_object_size(checkpoint_file)
        
        end = (obj_size if size == -1 else start + size) - 1
        s = start
        tasks = []
    
        # 進度計算
        total_bytes = end - start + 1
        downloaded_bytes = 0
    
        while s <= end:
            current_end = min(s + part_size - 1, end)
            task = threading.Thread(
                target=__range_get,
                args=(checkpoint_file, buffer, start, s, current_end, read_chunk_size, progress_callback, total_bytes)
            )
            tasks.append(task)
            task.start()
            s += part_size
    
        for task in tasks:
            task.join()
    
        time_end = time.time()
        # 顯示總耗時
        print(f"Downloaded {checkpoint_file} in {time_end - time_start:.2f} seconds.")
    
         # 計算並列印下載檔案的大小(單位:GB)
        file_size_gb = obj_size / (1024 * 1024 * 1024)
        print(f"Total downloaded file size: {file_size_gb:.2f} GB")
    
        buffer.seek(0)
        return buffer
    
    # 進度回呼函數
    def show_progress(downloaded, total):
        progress = (downloaded / total) * 100
        print(f"Progress: {progress:.2f}%", end="\r")
    
    # 調用樣本
    if __name__ == "__main__":
        # 調用 list_remote_models 方法列出遠程模型檔案
        models = list_remote_models()
        print("Remote models:", models)
    
        if models:
            # 選擇第一個模型檔案進行下載
            first_model = models[0]
            buffer = read_remote_model(first_model, progress_callback=show_progress)
            print(f"\nDownloaded {first_model} to buffer.")
  • 實驗結論

    版本

    OSS耗時 /s

    OSS平均頻寬 MB/s

    OSS峰值頻寬MB/s

    OSS pythonSDK

    109

    53

    100

    OSS pythonSDK(並發下載)

    11.1

    516

    600

    從實驗結果資料能夠明顯看出,相較於串列模式下的OSS Python SDK,並發下載模式下的耗時僅為前者的約0.2%,平均頻寬是前者的約9.7倍,峰值頻寬達到了前者的6倍。由此可見,在使用Python SDK進行AI模型訓練時,採用並發下載的方式能夠極大地提高處理效率,並大幅提升頻寬效能。

  • 其他方案

    除了單獨直接調用 SDK 這種方式,阿里雲還專門提供了一個名為osstorchconnector的Python庫,它主要用於在PyTorch訓練任務中高效地訪問和儲存OSS資料。該庫已經為使用者完成了並發的二次封裝,使用者可以直接使用。下面是有關使用osstorchconnector進行AI模型載入的測試結果。更多有關osstorchconnector的效能測試內容,請參見效能測試

    專案

    詳細資料

    實驗情境

    模型載入與聊天問答

    模型名稱

    gpt3-finnish-3B

    模型大小

    11 GB

    應用情境

    聊天問答

    硬體設定

    高規格ECS:96核(vCPU)、384 GiB記憶體、30 Gbps內網頻寬

    實驗結論

    平均頻寬約為10 Gbps,OSS服務端可支援10個任務同時載入模型