如何提升使用Boto3实现AWS S3跨桶文件传输的速度
问题根因分析
你当前代码的核心性能瓶颈是单线程串行执行S3对象复制操作:for循环中每一个文件的复制请求都需要等待上一个请求完全结束才会发起,140个对象排队执行自然耗时极高。而S3浏览器端的复制操作默认会并行发起多个请求,充分利用带宽,所以速度远快于你的串行实现。
优化方案
方案1:改造现有代码,增加多线程并行复制(最兼容现有业务逻辑)
S3复制属于IO密集型操作,使用多线程即可获得非常明显的性能提升,无需使用多进程。你可以用Python标准库的concurrent.futures.ThreadPoolExecutor实现,优化后代码示例如下:
import boto3 from concurrent.futures import ThreadPoolExecutor, as_completed from boto3.s3.transfer import TransferConfig # 配置传输参数:8MB以上文件自动分片,单文件最大并发10 transfer_config = TransferConfig( multipart_threshold=8 * 1024 * 1024, max_concurrency=10, use_threads=True ) s3 = boto3.resource('s3') client = boto3.client('s3') # 源桶配置 src_bucket_name = 'bucket_1' folder = "folder_1/subfolder_1" # 目标桶配置 dest_bucket_name = 'bucket_2' dest_prefix = 'folder_1/subfolder_1/' # 处理list_objects_v2分页,避免超过1000个对象时漏取 files_src = [] paginator = client.get_paginator('list_objects_v2') for page in paginator.paginate(Bucket=src_bucket_name, Prefix=folder): if 'Contents' in page: for obj in page['Contents']: ext = obj['Key'].split('.')[-1].lower() if ext in ['jpg','jpeg','png','tiff']: files_src.append(obj['Key']) # 复制单文件的函数 def copy_single_file(src_key): copy_source = { 'Bucket': src_bucket_name, 'Key': src_key } dest_key = dest_prefix + src_key s3.meta.client.copy(copy_source, dest_bucket_name, dest_key, Config=transfer_config) return f"完成复制: {src_key}" # 并行执行,线程数建议设置为10~30,根据实际情况调整避免触发S3限流 with ThreadPoolExecutor(max_workers=20) as executor: futures = [executor.submit(copy_single_file, src) for src in files_src] for future in as_completed(futures): # 可选打印进度 print(future.result())
该方案实测在140个对象1GB大小的场景下,耗时可以降到和浏览器操作相近的水平。
方案2:使用AWS S3 Batch Operations(适合大规模复制场景)
如果后续需要复制的对象数量达到万级甚至更高,推荐使用AWS托管的S3批量操作功能,你只需要提供待复制对象的清单,AWS会自动调度并行资源完成复制,内置错误重试、进度监控能力,无需自己维护并行逻辑。
方案3:直接使用AWS CLI(无需嵌入Python逻辑时首选)
如果复制操作不需要嵌入到你的Python业务流程中,直接用AWS CLI的aws s3 cp命令是成本最低的方案,CLI默认开启并行复制,还自带过滤逻辑,仅需一行命令即可完成操作:
aws s3 cp s3://bucket_1/folder_1/subfolder_1 s3://bucket_2/folder_1/subfolder_1 \ --recursive \ --exclude "*" \ --include "*.jpg" --include "*.jpeg" --include "*.png" --include "*.tiff"
额外优化建议
- 尽量将代码运行在和S3桶相同AWS区域的服务中(如EC2、Lambda、Cloud9),避免跨区域网络带来的延迟损耗,本地运行跨区域复制的速度通常会比同区域慢数倍。
- 线程数不要设置过高,S3对单账号的请求频率有默认限流阈值,过高的并发可能会触发限流反而降低速度,20左右的并发对大多数场景都是合适的。
内容的提问来源于stack exchange,提问作者Fraccalo
相关产品推荐
相关产品推荐

