【问题标题】:TooManyRequestsException for Boto3 Client OrganizationBoto3 客户端组织的 TooManyRequestsException
【发布时间】:2022-01-25 15:53:29
【问题描述】:

我正在通过 boto3 组织从主 AWS 账户中获取所有子账户。 代码工作正常。我能够获得儿童帐户列表。 但如果您再次运行我的 AWS Lambda 函数,则无法获取子账户。

出现以下错误:

Error while getting AWS Accounts : An error occurred (TooManyRequestsException) when calling the ListAccounts operation: AWS Organizations can't complete your request because another request is already in progress. Try again later

20 到 30 分钟后,我可以看到我的代码工作一次又一次地引发上述异常。

我是通过 AWS Gateway + AWS Lambda 运行此代码。

有什么想法吗?

代码:

import boto3
class Organizations(object):
    """AWS Organization"""
    def __init__(self, access_key, secret_access_key, session_token=None):
        self.client = boto3.client('organizations',
                                   aws_access_key_id=access_key,
                                   aws_secret_access_key=secret_access_key,
                                   aws_session_token=session_token
                                  )

    def get_accounts(self, next_token=None, max_results=None):
        """Get Accounts List"""
        if next_token and max_results:
            result = self.client.list_accounts(NextToken=next_token,
                                               MaxResults=max_results)
        elif next_token:
            result = self.client.list_accounts(NextToken=next_token)
        elif max_results:
            result = self.client.list_accounts(MaxResults=max_results)
        else:
            result = self.client.list_accounts()

        return result

class AWSAccounts(object):
    """ Return AWS Accounts information. """    
    def get_aws_accounts(self, access_key, secret_access_key, session_token):
        """ Return List of AWS account Details."""
        org_obj = Organizations(access_key=access_key,
                                secret_access_key=secret_access_key,
                                session_token=session_token)

        aws_accounts = []
        next_token = None
        next_result = None
        while True:
            response = org_obj.get_accounts(next_token, next_result)
            for account in response['Accounts']:
                account_details = {"name": account["Name"],
                                   "id": account["Id"],
                                   "admin_role_name": self.account_role_name
                                  }
                aws_accounts.append(account_details)

            if "NextToken" not in response:
                break
            next_token = response["NextToken"]

        return aws_accounts

【问题讨论】:

  • 这个错误的解释和其他人一样多:你调用 API 的次数太多并且受到速率限制。您需要考虑如何使用指数退避和/或某种形式的缓存来处理此问题。
  • 我同意。这只是一个电话。我调用 AWS API 的次数少于 20。我会准确计算我在 While Loop 中调用 AWS API 的次数。
  • @ydaetskcoR:函数运行一次时对 AWS API 的 11 次调用。然后在 TooManyRequestsExceptions 引发之前第二次调用 AWS API 7 到 8 次。
  • Boto3在一分钟内调用AWS API有什么限制吗?
  • 慢下来。这是关于错误的 AWS 文档:You've sent too many requests in too short a period of time. The limit helps protect against denial-of-service attacks. Try again later.

标签: python-3.x amazon-web-services aws-lambda boto3


【解决方案1】:

通过异常处理,我的代码运行成功了。

通过ClientError 异常捕获TooManyRequestsException 异常并通过boto3 重试调用AWS list_accounts API。

我们可以增加 0.1 秒的睡眠时间。

代码:

class AWSAccounts(object):
    """ Return AWS Accounts information. """  
    def get_accounts(self, next_token=None, max_results=None):
        """Get Accounts List"""
        # If Master AWS account contain more child accounts(150+) then
        # Too-Many-Request Exception is raised by the AWS API(boto3).
        # So to fix this issue, we are calling API again by Exception Handling.
        result = None
        while True:
            try:
                if next_token and max_results:
                    result = self.client.list_accounts(NextToken=next_token,
                                                       MaxResults=max_results)
                elif next_token:
                    result = self.client.list_accounts(NextToken=next_token)
                elif max_results:
                    result = self.client.list_accounts(MaxResults=max_results)
                else:
                    result = self.client.list_accounts()
            except botocore.exceptions.ClientError as err:
                response = err.response
                print("Failed to list accounts:", response)
                if (response and response.get("Error", {}).get("Code") ==
                        "TooManyRequestsException"):
                    print("Continue for TooManyRequestsException exception.")
                    continue

            break

        return result

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 2019-03-20
    相关资源
    最近更新 更多