【问题标题】:Concurrent.futures in AWS lambda function implementationAWS lambda 函数实现中的 Concurrent.futures
【发布时间】:2019-09-30 23:29:34
【问题描述】:

我正在使用 AWS Lambda python 函数将 EBS/RDS 快照复制到另一个区域以进行灾难恢复。 我遇到的问题是当时 5 个快照的复制限制。 如果我当时尝试复制超过 5 个,我会收到错误:

botocore.exceptions.ClientError: An error occurred (ResourceLimitExceeded) when calling the CopySnapshot operation: Too many snapshot copies in progress. The limit is 5 for this destination region. 

为了避免这种情况,我添加了一个等待函数,它检查目标区域中快照的状态,并在快照完成状态后继续循环。 它运行良好,但在这种情况下,它当时只处理一个快照。 问题是,如何为一个同时复制 5 个快照的并行任务实现 concurrent.futures 模块?

    waiter = client_ec2_dst.get_waiter('snapshot_completed')
    message = ""

    for i in ec2_snapshots_src:
            # snapshot_tags_filtered = ([item for item in i["Tags"] if item['Key'] != 'aws:backup:source-resource']
            # snapshot_tags_filtered.append({'Key': 'delete_On', 'Value': delete_on})
            # snapshot_tags_filtered.append({'Key': 'src_Id', 'Value': i["SnapshotId"]})
            try:
                response = client_ec2_dst.copy_snapshot(
                    Description='[Disaster Recovery] copied from us-east-1',
                    SourceRegion=region_src,
                    SourceSnapshotId=i["SnapshotId"],
                    DryRun=False,
                #           Encrypted=True,
                #           KmsKeyId='1e287363-89f6-4837-a619-b550ff28c211',
                )
                new_snapshot_id = response["SnapshotId"]
                waiter.wait(
                    SnapshotIds=[new_snapshot_id],
                    WaiterConfig={'Delay': 5, 'MaxAttempts': 120}
                )
                snapshot_src_name = ([dic['Value'] for dic in snapshot_tags_filtered if dic['Key'] == 'Name'])
                message += ("Started copying latest EBS snapshot: " + i["SnapshotId"] + " for EC2 instance: " + str(snapshot_src_name) + " from: " + region_src + " to: " + region_dst + " with new id: " + new_snapshot_id + ".\n")

                # Adding tags to snapshots in destination region
                tag_src = [new_snapshot_id]
                tag = client_ec2_dst.create_tags(
                    DryRun=False,
                    Resources=tag_src,
                    Tags=snapshot_tags_filtered
                )
            except Exception as e:
                raise e

【问题讨论】:

    标签: python amazon-web-services aws-lambda boto3 concurrent.futures


    【解决方案1】:

    您可以使用并发执行器和max_workers 参数来限制同时运行的作业数量。像这样:

    import concurrent.futures
    
    def copy_snapshot(snapshot_id):
        waiter = client_ec2_dst.get_waiter('snapshot_completed')
        response = client_ec2_dst.copy_snapshot(
            Description='[Disaster Recovery] copied from us-east-1',
            SourceRegion=region_src,
            SourceSnapshotId=snapshot_id,
            DryRun=False
        )
        new_snapshot_id = response["SnapshotId"]
        waiter.wait(
            SnapshotIds=[new_snapshot_id],
            WaiterConfig={'Delay': 5, 'MaxAttempts': 120}
        )
    
    # Copy snapshots in parallel, but no more than 5 at a time:
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = [
            executor.submit(copy_snapshot, s['SnapshotId'])
            for s in ec2_snapshots_src]
        for future in futures:
            future.result()
    

    【讨论】:

    • 我更新了问题描述中的代码,因为我传递了 snapshot_tags_filtered 变量并在循环中生成了一条消息。我很困惑如何实施您的解决方案。
    • 你可以把这个新逻辑放到copy_snapshot。这个新逻辑需要标签列表——它们可以作为第二个参数传递。或者它可以是单个参数,它是一个字典(来自ec2_snapshots_src 的单个项目)
    • 现在我修改了之前函数中的标签,所以我可以将它传递给copy_snapshot函数,谢谢。但是如何收集message函数每次执行时产生的数据呢?
    • 您可以从函数中返回它们,并通过在每个未来调用.result() 来收集返回值。像这样:messages = [f.result() for f in futures]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 2022-10-23
    • 2021-10-21
    • 2017-10-14
    • 2017-11-05
    • 2017-03-02
    相关资源
    最近更新 更多