架构设计容错篇之重试

avatar

概述

在微服务架构中,服务之间的调用并不像方法之间的调用那么稳定,它可能会因网络、磁盘、内存、CPU等硬件原因导致调用失败,也有可能是服务自身问题诸如调用超时、服务繁忙、服务不可用导致调用失败。
调用失败的原因各种各样,有些已经超出了我们的控制范围如网络抖动,丢包,也有些是我们提高程序处理能力可以有效减少的如超时,还有一些是短暂的、临时的失败不久之后可能会马上恢复诸如:网络抖动、服务繁忙、CPU高负载等等。
尽管有些失败不可控,但为了提高系统的稳定性,有些短暂的失败还是可以通过重试使其恢复正常的。

问题

在有些重要的服务调用中,如:支付服务调用订单服务通知其订单支付成功,如果服务调用失败且没有任何的补救措施,直接造成的影响就是用户付款了但收不到商品。
而失败的原因很可能是由于订单服务正在进行GC垃圾回收导致的请求超时,亦或者是订单服务负载过高本请求被拒绝处理。
不管怎么说,订单服务很可能在几秒之内恢复到正常状态,能够继续处理外部服务的请求。
所以,当失败是暂时的不久之后可恢复的,那么我们在失败之后进行重试,显然是一个可行的方案。

方案

针对可重试的失败,通常我们有下面几种常用的重试策略。

立即重试

如果失败的原因是瞬时的、偶发的,那么我们可以在调用失败后立即重试进行重试,以最快的速度自动恢复,从而降低系统的错误率。
比如,因网络瞬时抖动、数据库更新被锁定产生的调用失败,只要我们立即重试大概率就会成功。
但是,重试的次数不宜过多,因为立即重试会占用当前线程,线程得不到即时释放会增加服务自身的负载。

延迟重试

相反,如果原因不是瞬时而需要一小段时间系统才能恢复正常,那么我们可以在调用失败后每间隔一段时间重试一次,从而提高重试的成功率。
比如,服务提供方繁忙请求被拒、服务发版导致的短暂不可用,这些基本上可以通过延迟重试来使调用恢复正常。
既然,无法确定错误恢复的时长,那应该如何设置重试间隔时间?这就涉及到退避策略的选择了,常见的退避策略有下面这几种:

线性退避:调用失败后等待固定的时间后进行重试,直到重试次数耗尽;

随机退避:重试间隔时间不是固定的,每次间隔可能都不一样;

指数退避:调用失败后等待 2^x * n(n为重试间隔,x为重试次数)后,进行重试操作,这种退避策略可以有效的减少无效的重试。

但是,延迟重试如果延迟总时长过长,一般都需要进行异步处理,这种策略比较适合不依赖返回值的情况,如上面的订单通知。

异常分类重试

这是一种组合策略。为了更恰当的处理失败的调用,我们可以对引发失败的原因即程序异常进行分类,明确那些异常是可以重试的,那些是没有必要重试的,以及那些是可以立即重试的,那些是需要延迟重试的。
区分好后,就可以根据异常的重试特征选择要不要重试,如果是可重试的那么再进一步根据是否能立即重试从上面两个策略中选择一个合适的策略。

影响

虽然重试可以减少服务的错误率,但如果使用不当也会产生负面的影响,下面是在微服务架构中,使用重试常见的问题。

嵌套的重试

假设我们有三个服务分别是A、B、C,它们之间的依赖关系是A依赖B,B依赖C,A,B服务在调用下游服务的时候都使用了重试机制,并且重试次数都设置了3次。
如果很不幸C处于繁忙状态,导致所有的重试最终都以失败告终,即A第一次重试时,B重试三次都是失败;A第二次重试时,B重试三次也失败;A最后一次重试时,B重试三次还是失败。
那么这样的重试的次数便是指数级别的,位于最后一层的服务C被调用的次数便是其它服务重试次数的乘积,即9=3x3。
上面调用链上的重试机制是嵌套的,这种嵌套重试在最后一层服务不可用或繁忙时,其影响是灾难性的,会瞬间引发雪崩效应。
我们可以假设每秒的访问量是y,链路层级是l,每个服务的重试次数是n,那么重试的次数就可以通过该公式算出:y*n^(l-1)。比如,某个系统的每秒访问量是100,服务之间的链路层级是5层,每个服务的重试次数是3次,那么最后一层不可用的服务每秒的访问量便是8100次。

大多数公司都会使用第三方的微服务框架,那么可以通过框架的协议自下而上的透彻一个字段如retry-not-allowed,来标示上层服务不能进行重试。
也就是说,下层服务重试失败后,通过协议将该字段传递给调用它的服务消费者,服务消费者收到该字段就取消自己的重试机制,如此这般直至最上层的服务。
这样就可以避免嵌套重试的潜在风险,但是还有一个问题要注意,那就是超时的问题。
如果上层服务的调用的超时时间低于下层服务的调用超时时间,那么会造成下层服务的重试还在执行中,而上层服务就因为调用超时开始了下一次的重试。
这个问题同样也可以通过协议来解决,最上层的服务将自己的超时时间传递给下层服务,下层服务的超时时间只能在上层服务的超时范围之内,当然要减掉一些消耗时间如网络传输时间。

但是,如果下游服务长时间不可用,这样不停的重试也是会增加系统的负载的,访问量大的时候还是有引发雪崩效应的风险——如果线程资源都被重试的请求占用了其它请求得不要线程资源。
这个问题可以通过熔断、隔离、限流来解决,这里不再详述。

确保幂等

在对某个操作进行重试前,我们应该确保该同一操作无论发起多少次请求对数据的影响都是一致的,不会因为多次请求而产生副作用。
一般数据查询类操作是天然幂等的,而数据增、删、改则是非幂等的,需要做好幂等处理。

总结

重试是一把双刃剑,它既能帮助我们降低调用的失败率来提高系统的稳定性,也能在极端情况下引发系统雪崩,造成极大的损失。
因此,有些公司禁止程序员使用重试机制。我们不评价其规定是否合理,但可以看出如果滥用重试确实会造成极其负面的影响。
所以,在微服务的架构中,虽然重试可以有些提高系统的稳定性,但也要谨慎的使用重试以免造成不必要的损失。

扩展阅读

架构设计思维篇之结构

架构设计思维篇之概念

架构设计容错篇之重试

架构设计容错篇之熔断

架构设计容错篇之限流

架构设计事务篇之Mysql事务原理

架构设计事务篇之CAP定理

架构设计事务篇之分布式事务

架构设计消息篇之消息丢失

架构设计消息篇之保证消息顺序性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容