【问题标题】:Need advice to add exponenital back-off logic in AWS API in python需要建议在 python 中的 AWS API 中添加指数退避逻辑
【发布时间】:2017-07-16 18:27:35
【问题描述】:

我有一些 lambda 函数,它们正在用 python 编写多个 AWS Elastic beanstalk API 调用。它工作正常。但是从最近几天开始,我们遇到了节流错误。在与 AWS 讨论后,他们告诉在代码中添加指数回退逻辑。因此,如果它是节流阀,将在增量间隔重试相同的 API 调用。我知道他们在说什么以及它是如何工作的,但我不明白如何在我的代码中添加。他们有 CLI 的文档,但没有如下的 API,http://docs.aws.amazon.com/general/latest/gr/api-retries.html

谁能给我一个简单的例子,我们如何映射 API 调用的响应并重试,如果它像我在下面的代码中使用的一个 api 调用一样受到限制,

import boto3

conn = boto3.client('elasticbeanstalk')

response = conn.describe_environments(EnvironmentNames=["xyz"])

return response

我知道使用 if 条件执行此操作的简单方法,通过检查响应是否“超出速率”使用 while 我认为我可以实现这一点。但我想检查 CLI 示例中提供的内容,我该如何为 API 做类似的事情?

任何帮助将不胜感激!

【问题讨论】:

  • 我很高兴看到没有一百万巨魔抱怨“建议”一词并引用 Stackoverflow 规则书...

标签: python api amazon-web-services amazon-elastic-beanstalk


【解决方案1】:

您可以使用 proxy object 包裹任何 AWS 客户端对象并将一些 retrying logic 添加到代理对象:

from botocore.exceptions import ClientError
import retrying
import wrapt

class RetriedClient(wrapt.ObjectProxy):
"""Add retry logic to a boto3 client.

Wait 2^x * 1000 milliseconds between each retry, up to 10 seconds,
then 10 seconds afterwards.

"""

    def is_throttling_error(exception):
        """Botocore throws just a generic ClientError exception."""
        return isinstance(exception, ClientError) \
            and "RequestLimitExceeded" in exception.response

    @retrying.retry(
        wait_exponential_multiplier=1000,
        wait_exponential_max=10000, 
        retry_on_exception=is_throttling_error)
    def __getattr__(self, name):
        return getattr(self.__wrapped__, name)


# Create a boto3 client to Cloudformation
cf_client = boto3.client('cloudformation')

# Add exponential backoff retries to all client methods
wrapped_cf_client = RetriedClient(cf_client)

然后你可以像平常使用boto3的内置客户端一样使用wrapped_cf_client

resp = wrapped_cf_client.describe_stacks()

弃用说明:

在较新版本的botocore 中,有一种更好的方式来配置boto3 SDK 的重试逻辑。这从botocore 的版本1.6.0 开始工作:

from botocore.config import Config

config = Config(
    retries = dict(
        max_attempts = 10
    )
)

ec2 = boto3.client('ec2', config=config)

【讨论】:

  • 但是,即使异常不是ThrottlingException,您也在重试。这在某些情况下是有问题的......
  • @confiq 你当然是完全正确的。我应该说代码只是概念证明。我对其进行了修改,以便仅重试限制错误,但代码仍然很脆弱,因为 botocore 没有针对限制错误的特定异常,但它只是抛出了一个通用的ClientError。我还添加了一条弃用说明,因为在较新版本的 botocore 中不需要这样做。
  • 您的回答确实值得 +1!你怎么知道是1.10.4版本的botocore?
  • 我刚刚检查了我在测试 sn-p 的环境中拥有的 botocore.__version__ 的值,但我刚刚检查了来自 botocore 的发行说明,它是在 1.6.0 中添加的。我会更新答案。
猜你喜欢
  • 1970-01-01
  • 2011-04-21
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
相关资源
最近更新 更多