这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
重试是一种帮助避免远程函数调用偶发性错误的方法,本文将围绕重试的意义、重试的难点、重试策略三个方面来展开学习。
重试的意义
- 降低错误率
- 降低长尾延时
- 容忍暂时性错误
- 避开下游故障实例
重试的难点
重试的难点主要有幂等性、重试风暴、超时设置三点,下面主要对重试风暴进行介绍:
重试风暴与微服务的调用链路相关,通常微服务中的调用链路都很深,甚至能够达到几十层。因此,如果在第一个服务中就进行多次重试,那么在之后的服务中若都失败,针对前一个服务的每一个请求其自身都会向下重试多次,因此每次重试都会被放大,累积到链路很深时,重试次数将达到一个很大的值,导致整个服务发生雪崩。
重试策略
- 限制重试比例
设定一个重试比例阈值,使得重试次数占所有请求比例不超过该阈值。
- 防止链路重试
链路层面的防重试风暴的核心是限制每层都发生重试,理想情况下只有最下一层发生重试。通过向上层返回特殊的status表明“请求失败,但别重试”来实现这一操作。
- Hedged requests
对于可能超时的请求,重新向另一个下游实例发送一个相同的请求,并等待先到达的响应。由此实现通过重试去缩短服务的延迟。
总结
重试对于远程函数调用来说是一个有效避免偶发性错误的方案,但如何进行重试也需要讲究一定的策略。因为微服务中调用链路较深这一特性,会使得普通for循环的重试方式随服务层数的加深导致重试放大严重,甚至出现重试风暴等问题。文中提到的策略整体来说,都是针对减少微服务调用链路上的重试次数设定的。在链路中接入好的重试组件将使得重试得到很好的应用。