百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

系统设计:微服务重试机制(微服务 sentinel)

toqiye 2024-09-03 00:52 4 浏览 0 评论

为什么微服务重试机制很重要?

当我们单体应用时,所有的逻辑计算都在单一的进程中,除了进程断电外几乎不可能有处理失败的情况。然而,当我们把单体应用拆分为一个个细分的子服务后,服务间的互相调用无论是RPC还是HTTP,都是依赖于网络。

网络是脆弱的,不时请求会出现抖动失败。例如我们的 Server1 调用 Server2 进行下单时,可能网络超时了,这个时候 Server1 就需要返回给用户提示「网络错误」,这样我们的服务质量就下降了,可能会收到用户的投诉吐槽,降低产品竞争力。

这也是为什么很多产品内部都建设接口维度的 SLA 指标,当成功率低于一定程度时需要和负责人绩效挂钩以此来推进产品的稳定性。

对于网络抖动这种情况,解决的最简单办法之一就是重试


重试机制

重试机制:同步 、异步模式

常见的重试主要有两种模式:原地重试、异步重试。

原地重试很好理解,就是程序在调用下游服务失败的时候重新发起一次;异步重试是将请求信息丢到某个 mq 中,后续有一个程序消费到这个事件进行重试。

总的来说,原地重试实现简单,能解决大部分网络抖动问题,但是如果是服务追求强一致性,并且希望在下游故障的时候不影响正常服务计算,这个时候可以考虑用异步重试,上游服务可快速响应用户请求由异步消费者去完成重试。

重试算法

无论是异步还是同步模式,重试都有固定的几个算法:

  1. 线性退避:每次失败固定等待固定的时间
  2. 随机退避:每次失败等待随机的时间重试
  3. 指数退避:连续重试时,每次等待的时间都是前一次等待时间的倍数
  4. 综合退避:结合多种方式,比如线性 + 随机抖动、指数 + 随机抖动。加上随机抖动可以打散众多服务失败时对下游的重试请求,防止雪崩

为什么需要等待下再重试?

因为网络抖动或者下游负载高,马上重试成功的概率必然远远小于稍等一会再重试,相当于是让下游先喘一口气。

重试风暴

在微服务架构中,务必要注意避免重试风暴的产生。那么,什么是重试风暴呢?

如图所示,数据库出现了负载过高的情况,这个时候 Server 3 对它的请求会失败。但是因为配置了重试机制,Server 3 最多对数据库发起了3次请求。然而,这个时候荒唐的事情就出现了,为了避免抖动上游的每个服务都设置了超时重试3次的机制,这样明明是一次业务请求,在上述中由于有3个环节存在变成了对数据库的 27 (3 ^(n)) 次请求!这对原本就要崩溃的数据库,更是雪上加霜。

微服务架构通常一次请求会经过数个甚至数百个服务处理,如果每个都这样重试,数据库压力稍微彪高一点本身没啥问题,但是很可能就因为重试导致雪崩。


如何防止重试风暴

单实例限流

首先,我们接受请求的是单个实例(进程)中的线程,所以可以以单进程的粒度进行限流。

关于限流,我们常用的是令牌桶或者滑动窗口两种实现,这里简单实用滑动窗口实现。如下图所示,每秒会产生一个Bucket,我们在Bucket里记录这一秒内对下游某个接口的成功、失败数量。进而可以统计出每秒的失败率,结合失败率及失败请求数判断是否需要重试,每个 Bucket 在一定时间后过期。

如果下游大面积失败,这种时候是不适合重试的,我们可以配置一个比如失败率超过10%不重试的策略,这样在单机层面就可以避免很多不必要的重试。

  • 规范重试状态码

链路层面防止重试的最好做法是只在最下游重试(我们上面图的 Server3),Google SRE中指出了Google内部使用特殊错误码的方式来实现:

  • 约定一个特殊的业务状态码,它表示失败了,但是别重试
  • 任何一个环节收到下游这个错误,不会重试,继续透传给上游

通过这个模式,如果是数据库抖动情况下,只有最下游的三个重试请求,上游服务判断状态码知道不可重试不再重试。除此之外,在一些业务异常情况下也可通过状态码区分出无需重试的状态。

这个方法可以有效避免重试风暴,但是缺陷是需要业务方强耦合上这个状态码的逻辑,一般需要公司层面做框架上的约束


超时优化

在重试中,最头疼的莫过于超时这种场景。我们知道网络超时,有可能请求压根没到下游服务就产生了,也可能是已经到达下游并且被处理了,只是来不及返回,一个典型的两军问题

关于超时的情况,显然无法通过错误码识别,例如 A -> B -> C -> D 情况,如果C故障了,B可以获取到错误码,并返回给 A,但是因为 A 请求 B 超时了,所以是获取不到错误码的,这个时候 A 又会发起重试。那么针对超时的情况有没什么办法做优化,避免无必要的重试呢?

我认为有几个地方是可以做的:

  • 上游重试的请求不重试

超时导致的重试请求,在请求中带一个 Flag 标记。如果下游发现上游是因为超时而发起的请求,自己在请求下游时如果再超时出错,不再重试。例如 A -> B -> C 时,A 请求 B 超时重试,那么重试时会带上 Flag,B 发现 A 的重试请求中的 Flag,如果这个时候请求 C 失败,那么也不再重试请求,这样就避免了重试被放大。

  • 合理设置各个环节超时时间

A -> B -> C,B -> C 加上超时最多是 1s 时间,那么 A -> B 的超时时间要 >= 1秒,否则可能 B 对 C 的重试还没结束, A 就发起重试请求了。这类问题,我们可以通过分析离线数据发现环节中存在的不合理配置。

通过上述的优化,我们可以在一定程度上规避超时引发的重试风暴。


降低时延的重试

我们上文主要都在阐述为了保障请求 SLA 的重试以及规避重试风暴的手段,但是其实在实际应用过程中有一些低时延的业务场景也经常使用重试来优化,这个优化措施就是 backupRequest

比方说用户下单接口,我们希望更低的时延,因为延迟变高了用户可能下单量就减少了,直接影响到公司的盈利。假设我们的接口时延 p95 是 300ms,也就是95%的用户能在 300ms 内完成下单,虽然看起来很美好,但是可能存在 “长尾效应”,这尾部的 5% 对于业务来说也是至关重要的。

对于这种情况,常见的优化方案就是 backupRequest,简单来说策略就是这样的:

如果正常请求的超时时间是1s,那么当超时时间超过x ms(eg. 500ms)不等超时时间直接再发起一个相同的请求,如果旧的请求超时,新的请求正常落在300ms以内,那么我们这次请求不会超时且会在超时时间内完成。

这个机制对于时延敏感的业务非常有效,但是必须要保证请求是可重试的。


总结

这篇文章到这里就接近尾声了,如果你坚持读到这里,恭喜你已经掌握了微服务的重试机制,相信在工作中遇到的问题也都能游刃有余。下面我简单做下总结:

  1. 微服务重试很重要,因为可以避免一些网络波动导致的请求失败,提升服务稳定性
  2. 重试机制分为同步、异步两种模式,各有各的特性,需要结合业务选择
  3. 常见的重试算法有线性退避、指数退避、随机退避,以及结合其中两种的综合退避
  4. 重试风暴,在微服务中是一大隐患,我们可以通过单机重试限流以及约定重试状态码来规避
  5. 超时场景下的重试优化,上游因超时发起的流量,下游收到不再重复重试;合理配置链路超时时间
  6. 针对时延敏感业务,可使用 backup request 减轻长尾效应

相关推荐

完美解决MAC电脑空间不足问题(完美解决mac电脑空间不足问题的办法)

很多用MAC(苹果笔记本)电脑的人,特别是做iOS开发的,都会遇到一个头疼的问题,那就是电脑磁盘空间不足的问题。这个问题也困扰了我好久,我的开发机是256G的SSD(固态硬盘),但是用着用着就会空间不...

系统清理软件Omni Remover for Mac版

内容介绍你是否需要一款可以帮你清理Mac系统顽固垃圾的工具呢?试试OmniRemoverforMac吧!OmniRemoverMac版是一款运行在Mac平台上的系统清理软件。OmniRem...

mac上一款好用的多功能系统清理软件Omni Remover for Mac

mac上一款好用的多功能系统清理软件——OmniRemoverforMac。OmniRemovermac破解版是Mac平台上的一款软件清理工具。OmniRemoverMac版专为优化内存...

清理重建mac OS图标缓存(mac系统清空)

关于macos缓存问题你了解多少?今天macdown小编带大家了解下有关Mac清除图标缓存的相关知识!你知道吗?为了提升图形界面加载速度,默认情况下macOS针对Finder和Dock中的...

iOS 9 人机界面指南(五):图标与图形设计

来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。文章索引5.1图标与图像尺寸(IconandImageSizes)5.2应用图标(AppIcon)5.2....

你中招了吗?盘古团队发布XcodeGhost病毒检测应用

最近大批知名iOS应用被感染XcodeGhost病毒事件闹得沸沸扬扬,虽然该病毒作者发表声明称,XcodeGhost源于自己的实验,没有任何威胁性行为,同时公开了源代码。但依然无法消除众多用户的担忧,...

iOS应用感染Xcode真是无恶意实验?感染APP最新名单及版本号

前瞻科技快讯9月19日消息,一向号称是最安全的iOS真的不安全了?对于这两天闹得沸沸扬扬的多款iOS应用感染XcodeGhost病毒事件,今日凌晨4点左右,网友@XcodeGhost-Author在微...

苹果应用签名失败怎么处理(ios应用签名什么意思)

在移动应用开发过程中,苹果应用签名失败是一种常见的问题,它可能由多种原因引起。本文将介绍一些处理苹果应用签名失败的方法,帮助开发者解决这个问题。检查证书和描述文件:首先,开发者应该检查使用的证书和描述...

好用的系统扫描和清理工具推荐:OS Cleaner Pro for Mac

为大家推荐一款全面的系统扫描和清理工具,OSCleanerProforMac...

系统清理软件 Omni Remover for Mac

你是否需要一款可以帮你清理Mac系统顽固垃圾的工具呢?试试OmniRemoverforMac吧!OmniRemoverMac版是一款运行在Mac平台上的系统清理软件。OmniRemover...

优秀的Mac系统清理软件(mac清理系统占用空间)

OmniRemoverforMac是一款优秀的系统清理软件,功能有清洁卸载膨胀且顽固的应用程序,在macOSCatalina上清除32位不兼容的应用程序,iTunes,Xcode和Sketc...

苹果app安卓apk应用内用微信登录游戏时会显示登录失败怎么解决?

解决苹果iOS应用和安卓APK应用在使用微信授权登录时出现“登录失败,签名不一致”的问题,可以按照以下步骤进行排查和解决:1.核实AppID和AppSecret:确保iOS和安卓项目中使用的微信开放...

Cleaner for Xcode(遗留废弃文件清理工具)

Mac上的Xcode总是占用很大空间,并且用的时间越久越大!可通过删除不需要的和不建议使用的文件来帮助您加快Xcode的运行速度,你可以每月或者每周运行一次进行清理。有需要的朋友,赶快来下载吧~Cle...

Cleaner for Xcode mac(xcode清理工具)

Xcode文件太多,如何检测清理?试试CleanerforⅩcode吧!CleanerforXcodeforMac可以检测您的Xcode占用磁盘的情况,统计各个部件所占用的空间。并帮助您...

柠檬清理一款Mac设备必备的实用工具

简介柠檬清理是针对macOS系统专属制定的清理工具。主要功能包括重复文件和相似照片的识别、软件的定制化垃圾扫描、可视化的全盘空间分析、内存释放、浏览器隐私清理以及设备实时状态的监控等。重点聚焦清理功能...

取消回复欢迎 发表评论: