当我使用 s3.get_paginator('list_objects_v2') 时,AWS 错误“调用调用 API 操作失败并显示此消息:速率超出”

问题描述 投票:0回答:2

某些第三方应用程序一天内将大约 10000 个对象上传到我的存储桶+前缀。我的要求是获取过去 24 小时内上传到我的存储桶+前缀的所有对象。

我的bucket+前缀里有这么多文件。

所以我假设当我打电话时

response = s3_paginator.paginate(Bucket=bucket,Prefix='inside-bucket-level-1/', PaginationConfig={"PageSize": 1000})

那么它可能会多次调用 S3 API,这可能就是它显示 Rate Exceeded 错误的原因。

下面是我的 Python Lambda 函数。

import json
import boto3
import time
from datetime import datetime, timedelta


def lambda_handler(event, context):
    s3 = boto3.client("s3")
    from_date = datetime.today() - timedelta(days=1)
    string_from_date = from_date.strftime("%Y-%m-%d, %H:%M:%S")
    print("Date :", string_from_date)
    s3_paginator = s3.get_paginator('list_objects_v2')
    list_of_buckets = ['kush-dragon-data']
    bucket_wise_list = {}
    for bucket in list_of_buckets:

        response = s3_paginator.paginate(Bucket=bucket,Prefix='inside-bucket-level-1/', PaginationConfig={"PageSize": 1000})

        filtered_iterator = response.search(
            "Contents[?to_string(LastModified)>='\"" + string_from_date + "\"'].Key")

        keylist = []
        for key_data in filtered_iterator:

            if "/" in key_data:
                splitted_array = key_data.split("/")
                if len(splitted_array) > 1:
                    if splitted_array[-1]:
                        keylist.append(splitted_array[-1])
            else:
                keylist.append(key_data)

        bucket_wise_list.update({bucket: keylist})

    print("Total Number Of Object = ", bucket_wise_list)

    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps(bucket_wise_list)
    }

因此,当我们执行上面的 Lambda 函数时,它会显示以下错误。

“调用调用 API 操作失败,并显示以下消息:速率超出。”

任何人都可以帮助解决此错误并实现我的要求吗?

amazon-web-services amazon-s3 aws-lambda boto3 aws-sdk
2个回答
0
投票

这可能是由于您的帐户限制,您应该在重试之间添加几秒钟的重试或增加页面大小


0
投票

这很可能是由于您达到了 AWS S3 API 调用的配额限制。 “更大的锤子”解决方案是请求增加配额,但如果您不想这样做,还有另一种方法使用

botocore.Config
内置重试,例如:

import json
import time
from datetime import datetime, timedelta
from boto3 import client
from botocore.config import Config

config = Config(
   retries = {
      'max_attempts': 10,
      'mode': 'standard'
   }
)
def lambda_handler(event, context):
    s3 = client('s3', config=config)

###ALL OF YOUR CURRENT PYTHON CODE EXACTLY THE WAY IT IS###

此配置将使用指数增加的睡眠计时器来实现最大重试次数。来自文档:

  • 任何重试尝试都将包括以 2 为基数的指数退避,最大退避时间为 20 秒。

还有一种

adaptive
模式仍处于实验阶段。有关更多信息,请参阅有关 botocore.Config 重试
docs

另一个(在我看来不太健壮的)选择是编写自己的分页器,并在其中编程睡眠,尽管您可能只想在 99.99% 的情况下使用内置的退避功能(即使您确实必须编写自己的分页器)。 (此代码未经测试,甚至不是异步的,因此睡眠将不包括在页面响应的等待时间之外。要使“睡眠时间”精确到

sleep_secs
,您需要使用
concurrent.futures
asyncio
(AWS内置分页器主要使用
concurrent.futures
)):

from boto3 import client
from typing import Generator
from time import sleep

def get_pages(bucket:str,prefix:str,page_size:int,sleep_secs:float) -> Generator:
    s3 = client('s3')
    page:dict = client.list_objects_v2(
        Bucket=bucket,
        MaxKeys=page_size,
        Prefix=prefix
    )
    next_token:str = page.get('NextContinuationToken')
    yield page
    while(next_token):
        sleep(sleep_secs)
        page = client.list_objects_v2(
            Bucket=bucket,
            MaxKeys=page_size,
            Prefix=prefix,
            ContinuationToken=next_token
        )
        next_token = page.get('NextContinuationToken')
        yield page

© www.soinside.com 2019 - 2024. All rights reserved.