原文连接:https://mincong.io/cn/exponential-backoff-in-akka/
前言
在软件开发中,我们免不了要跟各种错误异常打交道。比如说,当一个服务在调用另一个服务的时候,很可能会出现一些错误,而且这些错误不一定跟业务逻辑相关。一些常见的错误是:大批量调用API,导致限流报错;网络不稳定,导致连接断开;对方服务器暂时不可用等等。面对这些问题,我们该如何处理呢?今天,让我们通过Akka这个框架来了解一下什么指数退避(Exponential Backoff)。
读完这篇文章,你会明白:
- 什么是指数退避?
- 如何理解它的各个参数?
- 它的一些应用场景
- 指数退避在别的框架中的实现
- 怎么从这篇文章拓展出去
事不宜迟,我们马上开始吧!
什么是指数退避
指数退避是退避技术(backoff)中很常见的一种,它是处理重负荷的一个很有效的方法。指数退避中最常用的估计是二进制退避技术。根据百度百科,二进制退避技术(Binary Exponential Backoff)指在遇到重复的冲突时,站点将重复传输,但在每一次冲突之后,随着时延的平均值将加倍。二进制指数退避算法提供了一个处理重负荷的方法。尝试传输的重复失败导致更长的退避时间,这将有助于负荷的平滑。如果没有这样的退避,以下状况可能发生:两个或多站点同时尝试传输,这将导致冲突,之后这些站点又立即尝试重传,导致一个新冲突。
啊,太抽象,看不懂?不要紧,那么让我来画个图帮助大家理解:
上面这幅图,它的横轴是时间,上面的点是发生异常和重试的时刻。第一次(0)收到服务器异常在第0秒,我们决定1秒以后重试;结果重试失败,第二次(1)再次重试,这时候重试时间翻倍,定在2秒以后;结果又失败,第三次(2)重试,这个时候重试时间再次翻倍,定在4秒以后。结果又失败,第四次(4)重试,这个时候重试时间再次翻倍,定在8秒以后…如此类推。这就是基本的二进制指数退避算法。
这里面涉及的两个基本参数:
- 初始退避时长(initial backoff duration):1秒
- 指数:2
Akka中的指数退避
在Akka中,创建一个普通的actor可以通过创造它的属性(Props)来实现,然后把props交给Akka系统:
var creatorProps = Props.create(
DocumentCreator.class,
() -> new DocumentCreator(externalServiceClient, managerRef, request));
如果要实现指数退避的话,那么可以不直接把props传递回去,而是先加入一个退避监督者(BackoffSupervisor),然后再返回:
var props = DocumentCreator.props(externalServiceClient, managerRef, request);
var creatorProps = BackoffSupervisor.props(
BackoffOpts.onFailure(props, "document-creator", minBackOff, maxBackOff, 0.1)
.withSupervisorStrategy(
new OneForOneStrategy(
DeciderBuilder.match(TooManyRequestsException.