GAE/P:为 RPC 调用实施指数退避
GAE/P: Implementing Exponential backoff for RPC calls
我知道当 RPC 调用失败时,指数退避是一件好事。到目前为止,在我的 GAE/P 应用程序中,我已经通过使用任务队列实现了指数退避:
deferred.defer(function_that_makes_RPC_call)
如果执行 RPC 调用的函数引发异常,任务队列的指数退避会处理它,我不必担心。
然而,一个问题是 deferred.defer 本身就是一个可能会失败的 RPC 调用!我有时会收到此错误:
DeadlineExceededError: The API call taskqueue.BulkAdd() took too long
to respond and was cancelled.
所以看来我不能再偷懒了,必须实现自己的指数退避。 :(
我正在考虑在 deferred.defer
周围放置一个包装器,它使用 backoff 实现指数退避,像这样:
@backoff.on_exception(backoff.expo,
(exception1, exception2, ...),
max_tries=8)
def defer_wrapper(function_that_makes_RPC_call):
deferred.defer(function_that_makes_RPC_call)
这里,装饰器实现了退避,当出现枚举的异常之一(例如,异常 1、异常 2 等)时会发生重试。
关于这个的几个问题:
- 这是实现指数退避的好解决方案吗?
- 我需要列出哪些例外情况?除了 DeadlineExceededError 之外还有什么?
我知道有我自己的指数退避然后提交到任务队列有点多余,但我认为 deferred.defer
应该比其他 RPC 调用更少失败,我想尽快回复请求。
特别是 DeadlineExceededError
尝试将延迟任务排入队列时,我只是进行 back2back 重试而不是使用指数退避 - 由于截止时间间隔到期本身,尝试将间隔 5 秒,在请求本身到达截止日期之前最多重试 12 次。
不过对于其他类型的故障可能是个好主意。
我知道当 RPC 调用失败时,指数退避是一件好事。到目前为止,在我的 GAE/P 应用程序中,我已经通过使用任务队列实现了指数退避:
deferred.defer(function_that_makes_RPC_call)
如果执行 RPC 调用的函数引发异常,任务队列的指数退避会处理它,我不必担心。
然而,一个问题是 deferred.defer 本身就是一个可能会失败的 RPC 调用!我有时会收到此错误:
DeadlineExceededError: The API call taskqueue.BulkAdd() took too long to respond and was cancelled.
所以看来我不能再偷懒了,必须实现自己的指数退避。 :(
我正在考虑在 deferred.defer
周围放置一个包装器,它使用 backoff 实现指数退避,像这样:
@backoff.on_exception(backoff.expo,
(exception1, exception2, ...),
max_tries=8)
def defer_wrapper(function_that_makes_RPC_call):
deferred.defer(function_that_makes_RPC_call)
这里,装饰器实现了退避,当出现枚举的异常之一(例如,异常 1、异常 2 等)时会发生重试。
关于这个的几个问题:
- 这是实现指数退避的好解决方案吗?
- 我需要列出哪些例外情况?除了 DeadlineExceededError 之外还有什么?
我知道有我自己的指数退避然后提交到任务队列有点多余,但我认为 deferred.defer
应该比其他 RPC 调用更少失败,我想尽快回复请求。
特别是 DeadlineExceededError
尝试将延迟任务排入队列时,我只是进行 back2back 重试而不是使用指数退避 - 由于截止时间间隔到期本身,尝试将间隔 5 秒,在请求本身到达截止日期之前最多重试 12 次。
不过对于其他类型的故障可能是个好主意。