如何在GitHub Actions中加速6对S3桶数据复制?矩阵策略可行吗?
S3桶数据复制任务优化:Matrix策略适用性与Boto3提速问题
问题描述
我有一个GitHub Actions任务,负责将6个源S3桶的数据复制到另外6个目标S3桶。由于需要先清空目标桶,整个流程耗时约30分钟。当前任务代码如下:
restore-s3: runs-on: ubuntu-latest timeout-minutes: 60 steps: - name: Assume Role uses: youyo/awscredswrap@v1.0.4 with: role_arn: ${{ secrets.AWS_EKS_IAM_ROLE }} duration_seconds: 3600 role_session_name: EKS env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ${{ env.AWS_ECR_REGION }} - name: restore S3 data id: s3_dir run: | release_version=${{ inputs.data_version }} echo $release_version aws s3 rm --recursive s3://test.qa.avatar.file-2027145436775700000001/ & aws s3 rm --recursive s3://test.qa.avatar.origin-2027145436939200000007/ & aws s3 rm --recursive s3://test.qa.documents.original-2027145436794600000003/ & aws s3 rm --recursive s3://test.qa.documents.sdf-2027145436895500000005/ & aws s3 rm --recursive s3://test.qa.templates.original-2027145436908800000006/ & aws s3 rm --recursive s3://test.qa.templates.sdf-2027145436788200000002/ & wait aws s3 cp --recursive "s3://test.qa.avatar.file/$release_version/" s3://test.qa.avatar.file-2027145436775700000001/ & aws s3 cp --recursive "s3://test.qa.avatar.origin/$release_version/" s3://test.qa.avatar.origin-2027145436939200000007/ & aws s3 cp --recursive "s3://test.qa.documents.original/$release_version/" s3://test.qa.documents.original-2027145436794600000003/ & aws s3 cp --recursive "s3://test.qa.documents.sdf/$release_version/" s3://test.qa.documents.sdf-2027145436895500000005/ & aws s3 cp --recursive "s3://test.qa.templates.original/$release_version/" s3://test.qa.templates.original-2027145436908800000006/ & aws s3 cp --recursive "s3://test.qa.templates.sdf/$release_version/" s3://test.qa.templates.sdf-2027145436788200000002/ & wait echo "Restore completed"
我想知道GitHub Actions的matrix策略是否适用于这个场景?另外我曾尝试编写Python Boto3脚本,但提速效果并不明显。
解答
1. GitHub Actions Matrix策略完全适用,且能显著提升效率
当前脚本是在单个runner实例内通过后台进程(& + wait)并行执行操作,但单个runner的CPU、网络带宽存在上限,无法充分利用多实例资源。Matrix策略可以将每一对桶的清空+复制操作分配到独立的runner实例中执行,突破单实例的资源瓶颈。
实现示例
jobs: restore-s3: runs-on: ubuntu-latest timeout-minutes: 60 strategy: matrix: bucket-pair: - source: "test.qa.avatar.file" target: "test.qa.avatar.file-2027145436775700000001" - source: "test.qa.avatar.origin" target: "test.qa.avatar.origin-2027145436939200000007" - source: "test.qa.documents.original" target: "test.qa.documents.original-2027145436794600000003" - source: "test.qa.documents.sdf" target: "test.qa.documents.sdf-2027145436895500000005" - source: "test.qa.templates.original" target: "test.qa.templates.original-2027145436908800000006" - source: "test.qa.templates.sdf" target: "test.qa.templates.sdf-2027145436788200000002" steps: - name: Assume Role uses: youyo/awscredswrap@v1.0.4 with: role_arn: ${{ secrets.AWS_EKS_IAM_ROLE }} duration_seconds: 3600 role_session_name: EKS env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: ${{ env.AWS_ECR_REGION }} - name: Restore S3 data for ${{ matrix.bucket-pair.target }} run: | release_version=${{ inputs.data_version }} echo "Processing: ${{ matrix.bucket-pair.source }} -> ${{ matrix.bucket-pair.target }}" # 清空目标桶 aws s3 rm --recursive s3://${{ matrix.bucket-pair.target }}/ # 复制指定版本数据 aws s3 cp --recursive "s3://${{ matrix.bucket-pair.source }}/$release_version/" s3://${{ matrix.bucket-pair.target }}/ echo "Completed restore for ${{ matrix.bucket-pair.target }}"
优势说明
- 每个job独立运行,GitHub会同时启动最多6个runner(匹配你的6对桶),并行执行清空和复制操作,总耗时会接近单个桶操作的时间(而非6倍时间)。
- 每个runner只处理一对桶,避免单实例内多进程竞争资源的问题,稳定性和效率都能提升。
2. Boto3脚本提速不明显的原因及优化方向
常见原因
- 未配置高效并行策略:默认Boto3的传输配置并发数较低,若用单线程执行,效率和aws cli差距大。
- 未启用分段传输:对于大文件,未开启Multipart Upload会导致传输速度受限。
- 单实例带宽瓶颈:即使Boto3实现了并行,单个runner的网络带宽依然是上限,和原cli脚本的单实例并行效果差异不大。
优化建议
- 调整Boto3传输配置:通过
TransferConfig提升并发数和分段传输效率,示例代码:import boto3 from boto3.s3.transfer import TransferConfig s3 = boto3.client('s3') config = TransferConfig( multipart_threshold=1024*25, # 25MB以上文件启用分段 max_concurrency=15, # 并发请求数 multipart_chunksize=1024*25, # 分段大小 use_threads=True # 启用线程池 ) # 清空目标桶 paginator = s3.get_paginator('list_objects_v2') for page in paginator.paginate(Bucket=target_bucket): if 'Contents' in page: s3.delete_objects( Bucket=target_bucket, Delete={'Objects': [{'Key': obj['Key']} for obj in page['Contents']]} ) # 复制数据 source_path = f"{source_bucket}/{release_version}/" paginator = s3.get_paginator('list_objects_v2') for page in paginator.paginate(Bucket=source_bucket, Prefix=f"{release_version}/"): if 'Contents' in page: for obj in page['Contents']: source_key = obj['Key'] target_key = source_key.replace(f"{release_version}/", "") s3.copy( {'Bucket': source_bucket, 'Key': source_key}, target_bucket, target_key, Config=config ) - 结合Matrix策略:将优化后的Boto3脚本放到Matrix的每个job中,让每个runner处理一对桶,利用多实例带宽进一步提速。
内容的提问来源于stack exchange,提问作者gamechanger17
相关产品推荐
相关产品推荐

