【问题标题】:Wrapping library functions to retry on 500 errors not working properly包装库函数以重试 500 错误无法正常工作
【发布时间】:2014-08-17 11:29:15
【问题描述】:

我正在尝试将所有函数包装在一个库实例中以重试 500 个错误(包装是为了避免强制团队成员在每个函数上专门添加重试代码)。我以前做过类似的事情,但对于 BigQuery,我没有运气。这是我的代码:

def bq_methods_retry(func):
    num_retries = 5
    @functools.wraps(func)
    def wrapper(*a, **kw):
        sleep_interval = 2
        for i in xrange(num_retries):
            try:
                return func(*a, **kw)
            except apiclient.errors.HttpError, e:
                if e.resp.status == 500 and i < num_retries-1:
                    logger.info("got a 500. retrying.")
                    time.sleep(sleep_interval)
                    sleep_interval = min(2*sleep_interval, 60)
                else:
                    logger.info('failed with unexpected apiclient error:')
                    raise e
            except:
                logger.info('failed with unexpected error:')
                raise
    return wrapper


def decorate_all_bq_methods(instance, decorator):
    for k, f in instance.__dict__.items():
        if inspect.ismethod(f):
            name = f.func_name
            setattr(instance, k, decorator(f))
    return instance

...
service = discovery.build('bigquery', 'v2', http=http)
#make all the methods in the service retry when appropriate
service = decorate_all_bq_methods(service, bq_methods_retry)
jobs = decorate_all_bq_methods(service.jobs(), bq_methods_retry)

然后,当我运行类似:

jobs.query(projectId=some_id, body=some_query).execute()

500 错误永远不会被 bq_methods_retry 捕获,而是传递给程序的其余部分。

有什么想法吗?我也愿意接受更好的重试解决方案。

【问题讨论】:

    标签: python google-bigquery python-decorators


    【解决方案1】:

    bq 命令行工具使用的 BigQuery 客户端通过包装 HTTP 对象来执行类似的操作。它不会重试,但会转换异常,因此您可能会使用相同类型的钩子。

    请注意,您可能需要小心重试某些类型的操作;例如,如果您重试附加数据的作业插入,如果它遇到返回响应的网络错误,则原始请求实际上可能会成功,因此您将插入相同的数据两次。为避免这种情况,您可以传入自己的作业 id,这样可以防止它运行两次(因为第二次作业已经存在)。

    查看代码here

    【讨论】:

    • 但是我没有在 HTTP 对象上执行。你能解释一下如何/为什么会这样吗?出于您提到的确切原因,我已经为所有插入和表创建提供了我自己的作业 ID,所以这应该不是问题。
    • 当您构建服务对象时,您将向其传递一个 HTP 对象,该对象将用于对 bigquery 的后续调用。因此,如果您使用将重试的东西包装该 http 对象,它应该适用于您进行的任何后续 bigquery 调用。
    猜你喜欢
    • 2012-02-19
    • 1970-01-01
    • 2019-03-28
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多