簡體   English   中英

如何在 Python 中使用線程來並行化 AWS S3 API 調用?

[英]How can I use threading in Python to parallelize AWS S3 API calls?

我編寫了一個 Python 腳本,試圖通過使用AWS Boto 3 list_objects() 方法來確定所有可用 AWS S3 存儲桶的總大小。

邏輯很簡單:

  1. 從每個 S3 存儲桶中獲取對象的初始列表(在 1,000 個對象后自動截斷)
  2. 遍歷對象列表中的每個對象,將該對象的大小添加到 total_size 變量中
  3. 當存儲桶仍有其他對象時,檢索它們並重復步驟 2

這是相關的代碼片段:

import boto3

s3_client = boto3.client('s3')

# Get all S3 buckets owned by the authenticated sender of the request
buckets = s3_client.list_buckets()

# For each bucket...
for bucket in buckets['Buckets']:
    # Get up to first 1,000 objects in bucket
    bucket_objects = s3_client.list_objects(Bucket=bucket['Name'])

    # Initialize total_size
    total_size = 0

    # Add size of each individual item in bucket to total size
    for obj in bucket_objects['Contents']:
        total_size += obj['Size']

    # Get additional objects from bucket, if more
    while bucket_objects['IsTruncated']:
        # Get next 1,000 objects, starting after final object of current list
        bucket_objects = s3_client.list_objects(
            Bucket=bucket['Name'],
            Marker=bucket_objects['Contents'][-1]['Key'])
        for obj in bucket_objects['Contents']:
            total_size += obj['Size']

    size_in_MB = total_size/1000000.0
    print('Total size of objects in bucket %s: %.2f MB'
        % (bucket['Name'], size_in_MB))

這段代碼在數據少於 5 MB 左右的存儲桶上運行速度相對較快,但是當我命中一個包含 90+ MB 數據的存儲桶時,執行時間從毫秒跳到 20-30+ 秒。

我希望使用線程模塊來並行化代碼的 I/O 部分(從 S3 獲取對象列表),以便在檢索它們的線程完成后立即添加存儲桶中所有對象的總大小而不是而不是必須按順序進行檢索和添加。

我知道 Python 由於 GIL 不支持真正的多線程,只是為了避免獲得對該效果的響應,但我的理解是,由於這是 I/O 操作而不是 CPU 密集型操作,因此線程模塊應該能夠提高運行時間。

我的問題與我在這里看到的幾個線程實現示例之間的主要區別在於,我沒有迭代已知列表或集合。 在這里,我必須首先檢索一個對象列表,查看該列表是否被截斷,然后根據當前列表中的最終對象的鍵檢索下一個對象列表。

誰能解釋一種改善此代碼運行時間的方法,或者在這種情況下不可能?

我遇到了類似的問題。

為每個線程創建一個單獨的會話似乎很重要。

所以代替

s3_client = boto3.client('s3')

你需要寫

s3_client = boto3.session.Session().client('s3')

否則線程相互干擾,會出現隨機錯誤。

除此之外,多線程的正常問題也適用。

我的項目是將 135,000 個文件上傳到 S3 存儲桶。 到目前為止,我發現使用 8 個線程可以獲得最佳性能。 否則需要 3.6 小時,現在需要 1.25 小時。

我有一個解決方案,它可能不適用於所有情況,但可以涵蓋很多場景。 如果您在子文件夾分層組織,那么對象首只使用機制列表子描述在這個崗位

然后使用這些獲得的前綴集將它們提交到多處理池(或線程池),其中每個工作人員將獲取特定於一個前綴的所有鍵,並使用多處理管理器將它們收集到共享容器中。 這樣,密鑰將被並行獲取。

如果密鑰分布均勻且分層,則上述解決方案將表現最佳,如果數據組織扁平,則效果最差。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM