微服务架构中的 熔断和降级

文章目录

  • 熔断
    • 判定服务的健康状态
    • 服务恢复正常
  • 降级
    • 跨服务降级
    • 自身服务提供有损服务
    • 具体案例分析

熔断

微服务架构中,如果需要保障可用性,其中一个方式就是 熔断。熔断在微服务架构里面是指 当微服务本身出现问题的时候,它会拒绝新的请求,直到微服务恢复。通过熔断机制可以给服务端恢复的时间,比如 CPU 使用率已经超出负载了,此时服务端触发了熔断,那么新来的请求就会被拒绝,因此,服务端的 CPU 使用率就会在一段时间内降到100%以内。

判定服务的健康状态

判断微服务是否出现了问题,需要根据自己的业务来选择一些指标来代表这个服务器的健康程度,一般可以使用 响应时间、错误率。不管选择什么指标,都要考虑两个因素: 一是阈值如何选择;二是超过阈值之后,要不要持续一段时间才触发熔断。

假设 把响应时间作为指标,如果业务对响应时间的要求是在 1s 以内,那么你的阈值就可以设定在 1s,或者稍高一点,留点容错的余地也可以,原则上阈值应该明显超过正常响应时间。比如经过一段时间的观测之后,发现这个服务的 99 线是 1s,那么你可以考虑将熔断阈值设定为 1.2s。

如果响应时间一旦超过了阈值,也不能立刻就熔断,而是 要求响应时间超过一段时间之后才触发熔断。这主要是出于两个考虑,一个是响应时间可能是偶发性地突然增长;另外一个则是防止抖动。这个“一段时间”很大程度上就依赖个人经验了,如果时间过短,可能会频繁触发熔断,然后又恢复,再熔断,再恢复…… 反过来,如果时间过长,就可能会导致需要触发熔断的时候却迟迟没有触发。你可以根据经验来设定一个值,比如说三十秒或者一分钟。

总结:为了保障微服务的可用性,在核心服务里面可以接入熔断,针对不同的服务,可以设计不同的微服务熔断策略。比如最简单的熔断策略就是根据响应时间来判定,当响应时间超过阈值一段时间之后就会触发熔断;一般会根据业务情况来选择这个阈值,如果产品方要求响应时间是1s,那么可以把阈值设定在1.2s。如果响应时间超过1.2s,并且持续三十秒,就会触发熔断。在触发熔断的情况下,新请求会被拒绝,而已有的请求还是会被继续处理,直到服务恢复正常。

还可以根据缓存策略设计熔断方案,比如某一个接口得并发很高,对缓存的依赖度非常严重,所以当检测到缓存不可用的时候(比如说 Redis 崩溃了),那么就会触发熔断,因为此时如果不熔断的话,高并发的请求会因为 Redis 崩溃而全部落到 MySQL 上,导致压垮 MySQL。
在触发熔断之后,可以额外开启一个线程(例如 Goroutine)持续不断地 ping Redis的服务是否正常,如果 Redis 恢复了,那么就退出熔断状态,新来的请求就不会被拒绝了。
这种方案类似于处理缓存雪崩的问题,参考:《缓存雪崩、缓存击穿、穿透穿透具体指哪些问题?》

服务恢复正常

如果我们判断一个服务响应时间过长,进入了熔断状态,那么一段时间(比如十分钟)过后,已接收的请求已经被处理完了,也就是服务已经恢复正常了,那么就需要退出熔断状态,继续接收新请求。因此在触发熔断之后,就要考虑检测服务是否已经恢复正常。

如果本身熔断是高并发引起的,那么在一分钟后并发依旧很高,这时候你一旦直接恢复正常,然后高并发的流量打过来,服务是不是又会触发熔断? 这就会出现上面说的“抖动”的情况。

所谓 抖动:就是服务频繁地在正常-熔断两个状态之间切换。引起抖动的原因是多样的,比如说前面提到的一旦超过阈值就进入熔断状态;再比如“一分钟后就认为服务已经恢复正常,继续处理新请求”就容易引发抖动问题。

要解决这个抖动问题,就需要在恢复之后控制住流量。比如说按照 10%、20%、30%……逐步递增,而不是立刻恢复 100% 的流量(需要负载均衡来配合)。在这种逐步放开流量的措施下,依旧有请求因为熔断不会被处理,那么有没有更好的处理方式?

其实,可以让客户端来控制这个流量。就是当服务端触发熔断之后,客户端就直接不再请求这个节点了,而是换一个节点。等到恢复了之后,客户端再逐步对这个节点放开流量。整体思路是利用负载均衡来控制流量,如果一个服务端节点触发了熔断,那么客户端在做负载均衡的时候就可以将这个节点挪出可用列表,后续请求会发给别的节点。在经过一段时间之后,客户端可以尝试发请求给该节点。如果该节点正确处理了,那客户端就可以加大流量,否则客户端就要再一次等待一段时间。

综合运用负载均衡和熔断的方案,重点在于客户端控制流量,并根据服务端节点的状况来操作可用节点列表。参考:《微服务的注册发现和微服务架构下的负载均衡》

万一所有可用节点都触发熔断了,应该怎么办? 如果因为某些原因数据库出问题,导致某个服务所有的节点都触发了熔断,那么客户端就完全没有可用节点了。针对这个问题,熔断解决不了,负载均衡也解决不了,只能通过监控告警之后人手工介入处理了。

整体流程:

  1. 服务端在触发熔断的时候,会返回一个代表熔断的错误。
  2. 客户端在收到这个错误之后,就会把这个服务端节点暂时挪出可用节点列表。后续所有的新请求都不会再打到这个触发了熔断的服务端节点上了。
  3. 客户端在等待一段时间后,逐步放开流量
  4. 如果服务端正常处理了新来的请求,那么客户端就加大流量。
  5. 如果服务端再次返回了熔断响应,那么客户端就会再一次将这个节点挪出可用列表。
  6. 如此循环,直到服务端完全恢复正常,客户端也正常发送请求到该服务端节点。

降级

降级就是在服务资源不够用的时候,停用一部分边缘业务,这部分被停用的边缘业务可以被理解为“全部熔断了”。

比如在双十一之类的大促高峰,电商平台可能会关闭一些服务(比如退款服务)用来保证订单业务尽可能不受影响(当然营销策略部分不在我们的讨论范围),这就是降级的典型应用,不过它是一种手动的跨服务降级。这种降级的好处有两方面:一方面是腾出了服务器资源,可以给订单服务或者支付服务;另外一方面是减少了对公共组件的压力,比如说减少了对数据库的写入压力。

关于服务降级,主要关心的也是两个方面,其一、如何判定一个服务要不要降级(如何判定服务健康);其二、降级之后怎么恢复,也是要考虑抖动的问题。熔断是彻底不提供服务,而降级则是尽量提供不分服务。

所以在一些场景下,既可以用熔断,也可以用降级。比如说在响应时间超过阈值之后,可以考虑选择熔断,完全不提供服务;也可以考虑降级,提供一部分服务。

原则上来说,是应该优先考虑使用降级的,然而有些服务是无法降级的,尤其是写服务。例如 你从前端接收数据,然后写到数据库,这种场景是无法降级的。另外,如果你希望系统负载尽快降低,那么熔断要优于降级。

如何降级?基本上可以分成两大类:跨服务降级 和 本服务提供有损服务。

跨服务降级

当服务资源不够的时候可以暂停某些服务,将腾出来的资源给其他更加重要、更加核心的服务使用。(上面提到的大促期间暂停退款服务就是跨服务降级的例子)。这种策略的要点是,必须要确定一个服务比另外一个服务更有业务价值,或者更加重要。

跨服务降级的措施常见的做法有三个:

  • 整个服务停掉,例如前面提到的停掉退款服务。
  • 停掉服务的部分节点,例如十个节点,停掉其中五个节点,这五个节点被挪作他用。
  • 停止访问某些资源。例如日志中心压力很大的时候,发信号给某些不重要的服务,让它们停止上传日志,只在本地保存日志。

跨服务降级可以在大部分合并部署的服务里面使用,一般的原则就是 B、C端合并部署降级 B 端;付费服务和非付费服务降级非付费服务。当然也可以根据自己的业务价值,将这些部署在同一个节点上的服务分成三六九等。而后在触发降级的时候从不重要的服务开始降级,将资源调配给重要服务。

自身服务提供有损服务

例如各大 App 的首页都会有降级的策略。在没有触发降级的时候,App 首页是针对你个人用户画像的个性化推荐。而在触发了降级之后,则可能是使用榜单数据,或者使用一个运营提前配置好的静态页面。这种策略的要点是你得知道你的服务调用者能够接受什么程度的有损。
在这里插入图片描述
针对服务本身的一些常见的降级思路:

  • 返回默认值,这算是最简单的一种状况。
  • 禁用可观测性组件,正常来说在业务里面都充斥了各种各样的埋点。这些埋点本身其实是会带来消耗的,所以在性能达到瓶颈的时候,就可以考虑停用,或者降低采样率。
  • 同步转异步,即正常情况下,服务收到请求之后会立刻处理。但是在降级的情况下,服务在收到请求之后只会返回一个代表“已接收”的响应。后续服务会异步地开启线程来处理,或者依赖于定时任务来处理。
  • 简化流程,如果你处理一个请求需要很多步骤,后续如果有一些步骤不关键的话,可以考虑不执行,或者异步执行。例如在内容生产平台,一般新内容要被推送到推荐系统里面。那么在降级的情况下你可以不推,而后可以考虑异步推送过去,也可以考虑等系统恢复之后再推送过去。

需要注意的是,在任何的故障处理里面,都要考虑恢复策略会不会引起抖动问题。

也可以考虑使用降级来保护 缓存-数据库 结构,一般来说,基本上都是先从缓存里面读数据,如果缓存里面没有数据,就从数据库中读取。那么在触发降级的情况下,可以考虑只从缓存里面读取,如果缓存里面没有数据,那么就直接返回,而不会再去数据库里读取。 这样可以保证在缓存里面有数据的那部分请求可以得到正常处理,也就是提供了有损服务。如果完全不考虑从数据库里取数据,那么你的性能瓶颈就完全取决于缓存,那么服务能够撑住的 QPS 会非常高。但是,如果缓存不命中的时候要去数据库取数据,那么服务的性能会衰退得非常快,即极少数缓存未命中的请求会占据大部分的系统资源。

具体案例分析

如果你的某个服务是同时提供了读服务和写服务,并且读服务明显比写服务更加重要,那么这时候你就可以考虑降级写服务。

假如说现在有一个针对商家的服务(比如 某团外卖),商家调用这些 API 来录入一些数据,比如他们门店的基本信息,上传一些门店图片等。同时还有一个针对 C 端普通用户的服务,这个服务就是把商家录入的数据展示在商家门店的首页上。所以你可以看到在这个场景下, 读服务 QPS 更高,也更加重要。那么如果这两个服务是一起部署的,在需要降级的时候,就可以考虑将针对商家的写服务停掉,将资源都腾出来给针对 C 端用户的读服务。从资源占用的角度分析,虽然整体来说写服务 QPS 占比很低,但是对于数据库来说,一次写请求对性能的压力要远比一次读请求大。所以暂停了写服务之后,数据库的负载能够减轻不少。

具体解决方案1( 读写服务中 降级写服务):接入一个跨服务的降级策略,当发现读服务的响应时间超过了阈值的时候,或者响应时间开始显著上升的时候,就将针对 B 端商家用户的服务临时停掉,腾出来的资源都给 C 端用户使用。对于 B 端用户来说,他们这个阶段是没有办法修改已经录入的数据的,但是这并不是一个特别大的问题。当 C 端接口的响应时间恢复正常之后,会自动恢复 B 端商家接口,商家又可以修改或者录入数据了。

在内容生产平台,作者生产内容,C 端用户查看生产的内容。那么在资源不足的情况下可以考虑停掉内容生产端的服务,只保留 C 端用户查看内容的功能。如果你的用户分成普通用户和 VIP 用户,那么你也可以考虑停掉给普通用户的服务。甚至,如果一个服务既提供给普通用户,也提供给 VIP 用户,你可以考虑将普通用户请求拒绝掉,只服务 VIP 用户。毕竟,VIP用户花钱了!

判断一个服务的业务价值最简单的方法就是判定什么业务带来了多少价值,又或者根据公司的主要营收来源确定服务的业务价值,越是能赚钱的就越重要。

具体解决方案2(快慢路径中 降级慢路径):在查询商品数据中,先查询缓存,如果缓存有数据,那么就直接返回。如果缓存没有,那么就需要去数据库查询。如果此时系统的并发非常高,那么就采取降级策略,将请求标记为降级请求。降级请求只会查询缓存,而不会查询数据库。如果缓存没有,那就直接返回错误。这样能够有效防止因为少部分请求缓存未命中而占据大量系统资源,导致系统吞吐量下降和响应时间显著升高。

这种思路其实可以在很多微服务里面应用。如果一个服务可以分成快路径和慢路径两种逻辑,那么在降级之前就可以先走快路径,再走慢路径。而触发了降级之后,就只允许走快路径。上面例子中,从缓存里加载数据就是快路径,从数据库里面加载数据就是慢路径。

慢路径还可以是发起服务调用或者复杂计算。比如说一个服务快路径是直接查询缓存,而慢路径可能是发起很多微服务调用,拿到所有响应之后一起计算,算出来一个结果并缓存起来。那么在降级的时候,可以有效提高吞吐量。不过这种吞吐量是有损的,毕竟部分请求如果没有在缓存中找到数据,那么就会直接返回失败响应。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/151189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《算法通关村——反转字符串中的单词问题解析》

《算法通关村——反转字符串中的单词问题解析》 151. 反转字符串中的单词 给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接…

大学生如何免费认证,下载,安装MATLAB

下载 打开学校图书馆官网 选择版本后,点击下载 注册绑定个人认证 前提!需要有学校邮箱【以edu.cn结尾的】 进入mathworks官网 注册账户 安装 下载完后,打开 选择:setup 安装程序 勾选:是;选择&#xf…

记GitLab服务器迁移后SSH访问无法生效的问题解决过程

公司IT心血来潮对GitLab服务器进行安全升级,升级后无法启动。。。只得启用备用服务器,具体的备份机制不祥,只知道原数据都在,但文件系统是否完全一样不清楚。切换为备用服务器后使用SSH下载代码死活不成功,反复提示需要…

机器学习第10天:集成学习

文章目录 机器学习专栏 介绍 投票分类器 介绍 代码 核心代码 示例代码 软投票与硬投票 bagging与pasting 介绍 核心代码 随机森林 介绍 代码 结语 机器学习专栏 机器学习_Nowl的博客-CSDN博客 介绍 集成学习的思想是很直观的:多个人判断的结合往往比…

身份证阅读器和社保卡读卡器Harmony鸿蒙系统ArkTS语言SDK开发包

项目需求,用ArkTS新一代开发语言实现了在Harmony鸿蒙系统上面兼容身份证阅读器和社保卡读卡器,调用了DonseeDeviceLib.har这个读卡库。 需要注意的是,鸿蒙系统的app扩展名为.hap,本项目编译输出的应用为:entry-default…

下厨房网站月度最佳栏目菜谱数据获取及分析PLus

目录 概要 源数据获取 写Python代码爬取数据 Scala介绍与数据处理 1.Sacla介绍 2.Scala数据处理流程 数据可视化 最终大屏效果 小结 概要 本文的主题是获取下厨房网站月度最佳栏目近十年数据,最终进行数据清洗、处理后生成所需的数据库表,最终进…

elmenetui表格二次封装包含查询框和分页

<!--dataList: 表格数据columnList: 表头字段 宽度minWidth使用slotName字段: 需要对列数据进行处理&#xff0c;不写prop字段&#xff0c;使用slotName字段btnText<String>: 按钮字段btnIcon<String>: 按钮的iconbtnEvent: 按钮事件btnType: 按钮类型getHeigh…

Go语言基础之基本语法

基本结构 package mainimport "fmt"func main() {fmt.Println("Hello,World!") }package mainimport ("fmt""log""net/http" )func handler(w http.ResponseWriter,r *http.Request) {s : "你好&#xff0c;世界&…

Dockerfile基础

前言 知识点整理 Dockerfile 简介 它是一个没有后缀名的文本文档&#xff0c;里面是组合镜像的一些命令&#xff0c;Docker build命令构建镜像时&#xff0c;通过读取Dockerfile中的指令的顺序&#xff08;自上到下&#xff09;自动生成镜像。 Dockerfile 命令 1. FROM 指…

JPA整合Sqlite解决Dialect报错问题, 最新版Hibernate6

前言 我个人项目中&#xff0c;不想使用太重的数据库&#xff0c;而内嵌数据库中SQLite又是最受欢迎的&#xff0c; 因此决定采用这个数据库。 可是JPA并不支持Sqlite&#xff0c;这篇文章就是记录如何解决这个问题的。 原因 JPA屏蔽了底层的各个数据库差异&#xff0c; 但是…

Android消息机制(Handler、Looper、MessageQueue)

一、ThreadLocal 1、什么是ThreadLocal ThreadLocal 是一个线程内部的数据存储类&#xff0c;通过它可以在指定的线程中存储数据&#xff0c;数据存储以后&#xff0c;只有在指定线程中可以获取到存储的数据&#xff0c;对于其他线程来说则无法获取到数据。 一般来说&#xf…

竞赛 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

说一说HTTP1.0、1.1、2.0版本区别和优化

说一说HTTP1.0、1.1、2.0版本区别和优化 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输超文本的应用层协议。 在不同的版本中&#xff0c;HTTP经历了一系列的演进和改进&#xff0c;主要包括HTTP 1.0、HTTP 1.1和HTTP 2.0。 下面详细解释它们之间…

亚马逊第二个大语言模型 Olympus 即将上线

据外媒爆料&#xff0c;亚马逊正在训练他的第二个大语言模型——Olympus&#xff0c;很有可能在今年12月份上线。亚马逊计划将Olympus接入在线零售商店、Echo等设备上的Alexa语音助手&#xff0c;并为AWS平台提供新的功能。据说这个大语言模型规模达到2万亿&#xff08;2000B&a…

C++ 删除无头链上所有指定值为x的节点。

C 删除无头链上所有指定值为x的节点。 #include<stdio.h> #include<ctype.h> #include<stdlib.h> typedef struct app {int data;struct app* next; }APP; int main() {int n;int node;int x;while (scanf("%d", &n) ! EOF){APP* head NULL, …

读《Segment Anything in Defect Detection》

摘要 (好像只是说把SAM应用到了红外缺陷分割领域) 引言 无损检测得到红外图像&#xff0c;根据热能观察异常 贡献&#xff1a; •从两个光学脉冲热成像系统构建广泛的缺陷热数据库&#xff0c;包括各种材料并释放它们。 • 开发DefectSAM&#xff0c;这是第一个用于缺陷检测…

maven升级版本后报错:Blocked mirror for repositories

出现问题的场景&#xff1a; 当 Maven 升级到3.8.1 之后&#xff0c;执行maven就会出现如下报错信息&#xff1a; maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories 原因&#xff1a; maven在3.8.1 的默认配置文件中增加了一组标签&#xff0…

MAC地址注册的网络安全影响和措施分析

MAC地址注册对网络安全具有重要影响&#xff0c;同时也需要采取相应的措施来应对潜在的安全风险。以下是有关MAC地址注册的网络安全影响和应对措施的分析&#xff1a; 影响&#xff1a; 1. 身份验证&#xff1a;MAC地址注册可用于设备的身份验证&#xff0c;但MAC地址本身并不…

033-从零搭建微服务-日志插件(一)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;mingyue: &#x1f389; 基于 Spring Boot、Spring Cloud & Alibaba 的分布式微服务架构基础服务中心 源…

【C/PTA】数组进阶练习(一)

本文结合PTA专项练习带领读者掌握数组&#xff0c;刷题为主注释为辅&#xff0c;在代码中理解思路&#xff0c;其它不做过多叙述。 目录 7-1 矩阵运算7-2 方阵循环右移7-3 螺旋方阵7-4 数组-杨辉三角7-5 数组-对角线求和7-6 数组-矩阵最小值 7-1 矩阵运算 给定一个nn的方阵&am…