Skip to content

什么是降级?

降级是从系统功能优先级的角度考虑如何应对系统故障。

服务降级指的是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

降级服务的特征如下

  1. 原因:整体负荷超出整体负载承受能力。
  2. 目的:保证重要或基本服务正常运行,非重要服务延迟使用或暂停使用
  3. 大小:降低服务粒度,要考虑整体模块粒度的大小,将粒度控制在合适的范围内
  4. 可控性:在服务粒度大小的基础上增加服务的可控性,后台服务开关的功能是一项必要配置(单机可配置文件,其他可领用数据库和缓存),可分为手动控制和自动控制。
  5. 次序:一般从外围延伸服务开始降级,需要有一定的配置项,重要性低的优先降级,比如可以分组设置等级 1-10,当服务需要降级到某一个级别时,进行相关配置

降级方式有哪些?

  • 延迟服务:比如发表了评论,重要服务,比如在文章中显示正常,但是延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行。
  • 在粒度范围内关闭服务(片段降级或服务功能降级):比如关闭相关文章的推荐,直接关闭推荐区
  • 页面异步请求降级:比如商品详情页上有推荐信息/配送至等异步加载的请求,如果这些信息响应慢或者后端服务有问题,可以进行降级;
  • 页面跳转(页面降级):比如可以有相关文章推荐,但是更多的页面则直接跳转到某一个地址
  • 写降级:比如秒杀抢购,我们可以只进行 Cache 的更新,然后异步同步扣减库存到 DB,保证最终一致性即可,此时可以将 DB 降级为 Cache。
  • 读降级:比如多级缓存模式,如果后端服务有问题,可以降级为只读缓存,这种方式适用于对读一致性要求不高的场景。

服务降级有哪些分类?

降级按照是否自动化可分为:

  • 自动开关降级(超时、失败次数、故障、限流)
  • 人工开关降级(秒杀、电商大促等)

自动降级分类又分为 :

  1. 超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况
  2. 失败次数降级:主要是一些不稳定的 api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况
  3. 故障降级:比如要调用的远程服务挂掉了(网络故障、DNS 故障、http 服务返回错误的状态码、rpc 服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)
  4. 限流降级:当我们去秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时开发者会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)

大规模分布式系统如何降级?

在大规模分布式系统中,经常会有成百上千的服务。在大促前往往会根据业务的重要程度和业务间的关系批量降级。这就需要技术和产品提前对业务和系统进行梳理,根据梳理结果确定哪些服务可以降级,哪些服务不可以降级,降级策略是什么,降级顺序怎么样。大型互联网公司基本都会有自己的降级平台,大部分降级都在平台上操作,比如手动降级开关,批量降级顺序管理,熔断阈值动态设置,限流阈值动态设置等等。

什么是熔断?

熔断是应对微服务雪崩效应的一种链路保护机制,类似股市、保险丝

微服务之间的数据交互是通过远程调用来完成的。服务 A 调用服务 B,服务 B 调用服务 C,某一时间链路上对服务 C 的调用响应时间过长或者服务 C 不可用,随着时间的增长,对服务 C 的调用也越来越多,然后服务 C 崩溃了,但是链路调用还在,对服务 B 的调用也在持续增多,然后服务 B 崩溃,随之 A 也崩溃,导致雪崩效应

服务熔断是应对雪崩效应的一种微服务链路保护机制。例如在高压电路中,如果某个地方的电压过高,熔断器就会熔断,对电路进行保护。同样,在微服务架构中,熔断机制也是起着类似的作用。当调用链路的某个微服务不可用或者响应时间太长时,会进行服务熔断,不再有该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。

服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。

降级和熔断有什么区别?

熔断和降级是两个比较容易混淆的概念,两者的含义并不相同。

降级的目的在于应对系统自身的故障,而熔断的目的在于应对当前系统依赖的外部系统或者第三方系统的故障。

有哪些现成解决方案?

Spring Cloud 官方目前推荐的熔断器组件如下:

  • Hystrix
  • Resilience4J
  • Sentinel
  • Spring Retry

我们单独拎出 Sentinel 和 Hystrix 来说一下(没记错的话,Hystrix 目前已经没有维护了。)。

Hystrix 是 Netflix 开源的熔断降级组件,Sentinel 是阿里中间件团队开源的一款不光具有熔断降级功能,同时还支持系统负载保护的组件。

简单来说,两者都是主要做熔断降级的 ,那么两者到底有啥异同呢?该如何选择呢?

Sentinel 的 wiki 中已经详细描述了其与 Hystrix 的区别,地址:https://github.com/alibaba/Sentinel/wiki/Sentinel-与-Hystrix-的对比

下面这个详细的表格就来自 Sentinel 的 wiki。

<table data-lake-id="cUEkq" id="cUEkq" margin="true" class="lake-table" style="width: 750px"><colgroup><col width="250"><col width="250"><col width="250"></colgroup><tbody><tr data-lake-id="u0e1620ad" id="u0e1620ad"><td data-lake-id="u5279d433" id="u5279d433"></td><td data-lake-id="ufbc5a0e9" id="ufbc5a0e9"><p data-lake-id="uc15cac77" id="uc15cac77"><span data-lake-id="u799eeddc" id="u799eeddc">Sentinel</span></p></td><td data-lake-id="u18e9ce48" id="u18e9ce48"><p data-lake-id="u95de9403" id="u95de9403"><span data-lake-id="u94261f50" id="u94261f50">Hystrix</span></p></td></tr><tr data-lake-id="u3814c699" id="u3814c699"><td data-lake-id="u96b00e19" id="u96b00e19"><p data-lake-id="u2b727583" id="u2b727583"><span data-lake-id="ub1e26ceb" id="ub1e26ceb">隔离策略</span></p></td><td data-lake-id="u100b854e" id="u100b854e"><p data-lake-id="u9c42be31" id="u9c42be31"><span data-lake-id="u039a16d3" id="u039a16d3">信号量隔离</span></p></td><td data-lake-id="u5cacd95d" id="u5cacd95d"><p data-lake-id="ud67d6ff3" id="ud67d6ff3"><span data-lake-id="u8d854512" id="u8d854512">线程池隔离/信号量隔离</span></p></td></tr><tr data-lake-id="uffc7a9e1" id="uffc7a9e1"><td data-lake-id="uc8d43307" id="uc8d43307"><p data-lake-id="uddb7b0ea" id="uddb7b0ea"><span data-lake-id="ub36ac371" id="ub36ac371">熔断降级策略</span></p></td><td data-lake-id="ue6cb6f85" id="ue6cb6f85"><p data-lake-id="u28055991" id="u28055991"><span data-lake-id="u5e3597e7" id="u5e3597e7">基于响应时间或失败比率</span></p></td><td data-lake-id="u352c23ff" id="u352c23ff"><p data-lake-id="u8316ac29" id="u8316ac29"><span data-lake-id="u261ba2fb" id="u261ba2fb">基于失败比率</span></p></td></tr><tr data-lake-id="ub30b7bcb" id="ub30b7bcb"><td data-lake-id="u8ae58651" id="u8ae58651"><p data-lake-id="ub19b8cee" id="ub19b8cee"><span data-lake-id="u2e7319c5" id="u2e7319c5">实时指标实现</span></p></td><td data-lake-id="udaef9639" id="udaef9639"><p data-lake-id="ub16572f7" id="ub16572f7"><span data-lake-id="u3d46edd5" id="u3d46edd5">滑动窗口</span></p></td><td data-lake-id="uf48604bb" id="uf48604bb"><p data-lake-id="uc8025c00" id="uc8025c00"><span data-lake-id="u4825e00d" id="u4825e00d">滑动窗口(基于 RxJava)</span></p></td></tr><tr data-lake-id="u1fb76ece" id="u1fb76ece"><td data-lake-id="uf15242a1" id="uf15242a1"><p data-lake-id="u18ac8ba3" id="u18ac8ba3"><span data-lake-id="u24b128db" id="u24b128db">规则配置</span></p></td><td data-lake-id="ufbacffdb" id="ufbacffdb"><p data-lake-id="u8f082e3a" id="u8f082e3a"><span data-lake-id="u848fba3a" id="u848fba3a">支持多种数据源</span></p></td><td data-lake-id="uc25db310" id="uc25db310"><p data-lake-id="u07dd9958" id="u07dd9958"><span data-lake-id="u69ae50a5" id="u69ae50a5">支持多种数据源</span></p></td></tr><tr data-lake-id="u84279234" id="u84279234"><td data-lake-id="ue22a7aa0" id="ue22a7aa0"><p data-lake-id="ue4af6796" id="ue4af6796"><span data-lake-id="u0e43e096" id="u0e43e096">扩展性</span></p></td><td data-lake-id="ucd5150b5" id="ucd5150b5"><p data-lake-id="u9dbebb61" id="u9dbebb61"><span data-lake-id="u90e29083" id="u90e29083">多个扩展点</span></p></td><td data-lake-id="ud59314be" id="ud59314be"><p data-lake-id="udac4ad2b" id="udac4ad2b"><span data-lake-id="ua567d682" id="ua567d682">插件的形式</span></p></td></tr><tr data-lake-id="ubb3e8b70" id="ubb3e8b70"><td data-lake-id="u84dd57b4" id="u84dd57b4"><p data-lake-id="u0ed190f1" id="u0ed190f1"><span data-lake-id="ud602ea6c" id="ud602ea6c">基于注解的支持</span></p></td><td data-lake-id="u7814ec37" id="u7814ec37"><p data-lake-id="u228d94ee" id="u228d94ee"><span data-lake-id="ube833fc5" id="ube833fc5">支持</span></p></td><td data-lake-id="u18666dc3" id="u18666dc3"><p data-lake-id="uae7ee0c5" id="uae7ee0c5"><span data-lake-id="u4785d93b" id="u4785d93b">支持</span></p></td></tr><tr data-lake-id="u57860fed" id="u57860fed"><td data-lake-id="u2d71593f" id="u2d71593f"><p data-lake-id="u8abc0852" id="u8abc0852"><span data-lake-id="u1b869879" id="u1b869879">限流</span></p></td><td data-lake-id="u04620ae2" id="u04620ae2"><p data-lake-id="uf66a3016" id="uf66a3016"><span data-lake-id="u82d8b15e" id="u82d8b15e">基于 QPS,支持基于调用关系的限流</span></p></td><td data-lake-id="u03ededbb" id="u03ededbb"><p data-lake-id="uf0e5f32e" id="uf0e5f32e"><span data-lake-id="u7cae0332" id="u7cae0332">有限的支持</span></p></td></tr><tr data-lake-id="u46a11f54" id="u46a11f54"><td data-lake-id="ue3f89dcc" id="ue3f89dcc"><p data-lake-id="uf03e6d04" id="uf03e6d04"><span data-lake-id="uecda25ae" id="uecda25ae">流量整形</span></p></td><td data-lake-id="u79db1a63" id="u79db1a63"><p data-lake-id="ub7a40780" id="ub7a40780"><span data-lake-id="u8d27f9c4" id="u8d27f9c4">支持慢启动、匀速器模式</span></p></td><td data-lake-id="u47584ffe" id="u47584ffe"><p data-lake-id="uac9ab974" id="uac9ab974"><span data-lake-id="u48992cae" id="u48992cae">不支持</span></p></td></tr><tr data-lake-id="u7e9a548c" id="u7e9a548c"><td data-lake-id="u07f76f42" id="u07f76f42"><p data-lake-id="u335ea789" id="u335ea789"><span data-lake-id="u0b2cc4dd" id="u0b2cc4dd">系统负载保护</span></p></td><td data-lake-id="ub083d9ee" id="ub083d9ee"><p data-lake-id="ua10fbbc8" id="ua10fbbc8"><span data-lake-id="u36b9811f" id="u36b9811f">支持</span></p></td><td data-lake-id="uffcccc65" id="uffcccc65"><p data-lake-id="ub1458f83" id="ub1458f83"><span data-lake-id="u63e0c124" id="u63e0c124">不支持</span></p></td></tr><tr data-lake-id="udb20a9ef" id="udb20a9ef"><td data-lake-id="u93d46915" id="u93d46915"><p data-lake-id="u57461e77" id="u57461e77"><span data-lake-id="u6b1d3616" id="u6b1d3616">控制台</span></p></td><td data-lake-id="u79831156" id="u79831156"><p data-lake-id="u373bfc55" id="u373bfc55"><span data-lake-id="ub38a4452" id="ub38a4452">开箱即用,可配置规则、查看秒级监控、机器发现等</span></p></td><td data-lake-id="u4a9ae295" id="u4a9ae295"><p data-lake-id="ue505cda8" id="ue505cda8"><span data-lake-id="ufad72438" id="ufad72438">不完善</span></p></td></tr><tr data-lake-id="u2c301ed3" id="u2c301ed3"><td data-lake-id="uf0a40c13" id="uf0a40c13"><p data-lake-id="u35df938f" id="u35df938f"><span data-lake-id="u7af9edf8" id="u7af9edf8">常见框架的适配</span></p></td><td data-lake-id="u91c515bf" id="u91c515bf"><p data-lake-id="uc8b3aa1d" id="uc8b3aa1d"><span data-lake-id="u8e643946" id="u8e643946">Servlet、Spring Cloud、Dubbo、gRPC 等</span></p></td><td data-lake-id="u5f697376" id="u5f697376"><p data-lake-id="ub8d75b23" id="ub8d75b23"><span data-lake-id="u45c68c25" id="u45c68c25">Servlet、Spring Cloud Netflix</span></p></td></tr></tbody></table>

如果你想了解 Sentinel、Hystrix、resilience4j 三者的对比的话,可以查看 Sentinel 的相关 wiki :https://github.com/alibaba/Sentinel/wiki/Guideline:-从-Hystrix-迁移到-Sentinel#功能对比

推荐阅读

参考

文章来源于自己总结和网络转载,内容如有任何问题,请大佬斧正!联系我