随着公司业务不断的复杂化,随之而来的就是微服务的爆发式增长,流量一下就起来了,对于网关来说就不得不考虑服务的保护了,也就是下面讲到的降级,限流和熔断
1. 服务降级的设计
什么是服务降级?
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
服务降级的目标
保证核心服务可用,非核心服务弱可用,甚至不可用
服务降级的层级
服务层降级
- SLB (Service Load Balance)
- Nginx / Apache
- Spring Cloud Gateway
- Microservice
数据层DB降级
1.1 降级分类
降级按照是否自动化可分为:自动开关降级和人工开关降级。 降级按照功能可分为:读服务降级、写服务降级。 降级按照处于的系统层次可分为:多级降级。
详情可参考:架构设计 -- 服务降级策略详解
1.2 自动降级分类
超时降级 —— 主要配置好超时时间和超时重试次数和机制,并使用异步机制探测恢复情况
失败次数降级 —— 主要是一些不稳定的API,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况
故障降级 —— 如要调用的远程服务挂掉了(网络故障、DNS故障、HTTP服务返回错误的状态码和RPC服务抛出异常),则可以直接降级
限流降级 —— 当触发了限流超额时,可以使用暂时屏蔽的方式来进行短暂的屏蔽
1.3 服务降级 - 分布式开关
我们可以设置一个分布式开关,用于实现服务的降级,然后集中式管理开关配置信息即可。具体方案如下
1.启动拉取配置,并启动定时拉取和订阅配置信息。 2.可视化管理端变更配置项 3.操作配置中心配置信息 4.通知或被定时拉取最新配置,然后变更内存中的配置信息
1.4 服务降级 - 配置中心
微服务降级的配置信息是集中式的管理,然后通过可视化界面进行友好型的操作。配置中心和应用之间需要网络通信,因此可能会因网络闪断或网络重启等因素,导致配置推送信息丢失、重启或网络恢复后不能再接受、变更不及时等等情况,因此服务降级的配置中心需要实现以下几点特性,从而尽可能的保证配置变更即使达到
启动主动拉取配置 —— 用于初始化配置(减少第一次定时拉取周期)
发布订阅配置 —— 用于实现配置及时变更(可以解决90%左右的配置变更)
定时拉取配置 —— 用于解决发布订阅失效或消失丢失的情况(可以解决9%左右的发布订阅失效的消息变更)
离线文件缓存配置 —— 用于临时解决重启后连接不上配置中心的问题
可编辑式配置文档 —— 用于直接编辑文档的方式来实现配置的定义
提供Telnet命令变更配置 —— 用于解决配置中心失效而不能变更配置的常见
1.5 服务降级要考虑的问题
核心和非核心服务(核心服务 - 中台服务,和钱打交道的服务 非核心 - OA服务)
是否支持降级,降级策略
业务放通的场景,策略
1.6 处理策略
当触发服务降级后,新的请求再次到达时,我们该如何来处理这些请求呢?从微服务架构全局的视角来看,我们通常有以下是几种常用的降级处理方案:
页面降级 —— 可视化界面禁用点击按钮、调整静态页面
延迟服务 —— 如定时任务延迟处理、消息入MQ后延迟处理
写降级 —— 直接禁止相关写操作的服务请求
读降级 —— 直接禁止相关度的服务请求
缓存降级 —— 使用缓存方式来降级部分读频繁的服务接口
1.6.1 读写请求降级的服务降级手段
1.关闭部分服务(业务相关)
2.拒绝部分请求
2.1 拒绝部分老请求 - 减轻微服务请求处理的数量 - 确保“新”请求正常响应 - RPC 队列方式 请求入队,出队时间处理 2.2 优先级请求方式 - 非核心功能直接丢弃 - 业务紧密 2.3 随机拒绝方式 - 随机丢掉一定比例的请求,网站一会可用一会不可用
针对后端代码层面的降级处理策略,则我们通常使用以下几种处理措施进行降级处理
抛异常
返回NULL
调用Mock数据
调用Fallback处理逻辑
1.7 服务降级 - 高级特性
我们已经为每个服务都做好了一个降级开关,也已经在线上验证通过了,感觉完全没问题了。
场景一:某一天,运营搞了一次活动,突然跑过来说,现在流量已经快涨到上限了,有没有批量降级所有不重要服务的方式?开发一脸懵逼的看着,这又不是操作DB,哪里有批量操作呀。
场景二:某一天,运营又搞事了,说我们等下要搞一个活动,让我们赶紧提前把不重要的服务都降级了,开发又是一脸懵逼,我怎么知道要降级哪些服务呀。
反思:服务降级的功能虽然是实现了,可是没有考虑实施时的体验。服务太多,不知道该降级哪些服务,单个操作降级速度太慢……
1.7.1 分级降级
当微服务架构发生不同程度的情况时,我们可以根据服务的对比而进行选择式舍弃(即丢车保帅的原则),从而进一步保障核心的服务的正常运作。
如果等线上服务即将发生故障时,才去逐个选择哪些服务该降级、哪些服务不能降级,然而线上有成百上千个服务,则肯定是来不及降级就会被拖垮。同时,在大促或秒杀等活动前才去梳理,也是会有不少的工作量,因此建议在开发期就需要架构师或核心开发人员来提前梳理好,是否能降级的初始评估值,即是否能降级的默认值。
为了便于批量操作微服务架构中服务的降级,我们可以从全局的角度来建立服务重要程度的评估模型,如果有条件的话,建议可以使用 层次分析法(The analytic hierarchy process,简称AHP) 的数学建模模型(或其它模型)来进行定性和定量的评估(肯定比架构师直接拍脑袋决定是否降级好很多倍,当然难度和复杂度也会高许多,即你需要一个会数学建模人才),而层次分析法的基本思路是人对一个复杂的决策问题的思维和判断过程大体上是一样的。
以下是个人给出的最终评价模型,可作为服务降级的评价参考模型进行设计
我们利用数学建模的方式或架构师直接拍脑袋的方式,结合服务能否降级的优先原则,并根据台风预警(都属于风暴预警)的等级进行参考设计,可将微服务架构的所有服务进行故障风暴等级划分为以下四种
评估模型
蓝色风暴 (S4)—— 表示需要小规模降级非核心服务
黄色风暴 (S3)—— 表示需要中等规模降级非核心服务
橙色风暴(S2) —— 表示需要大规模降级非核心服务
红色风暴 (S1)—— 表示必须降级所有非核心服务
设计说明
故障严重程度为:S4<S3<S2<S1
建议根据二八原则可以将服务划分为:80%的非核心服务+20%的核心服务
以上模型只是整体微服务架构的服务降级评估模型,具体大促或秒杀活动时,建议以具体主题为中心进行建立(不同主题的活动,因其依赖的服务不同,而使用不同的进行降级更为合理)。当然模型可以使用同一个,但其数据需要有所差异。最好能建立一套模型库,然后实施时只需要输入相关服务即可输出最终降级方案,即输出本次大促或秒杀时,当发生蓝色风暴时需要降级的服务清单、当发生黄色风暴时需要降级的服务清单……
1.7.2 降级权值
微服务架构中有服务权值的概念,主要用于负载时的权重选择,同样服务降级权值也是类似,主要用于服务降级选择时的细粒度优先级抉择。所有的服务直接使用以上简单的四级划分方式进行统一处理,显然粒度太粗,或者说出于同一级的多个服务需要降级时的降级顺序该如何?甚至我想要人工智能化的自动降级,又该如何更细粒度的控制?
基于上述的这些AI化的需求,我们可以为每一个服务分配一个降级权值,从而便于更加智能化的实现服务治理。而其评估的数值,同样也可以使用数学模型的方式进行定性与定量的评估出来,也可以架构师根据经验直接拍脑袋来确定。
2. 服务限流的设计
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。
2.1 服务限流应该怎么做?
对系统服务进行限流,一般有如下几个模式
1.熔断: 这个模式是需要系统在设计之初,就要把熔断措施考虑进去。当系统出现问题时,如果短时间内无法修复,系统要自动做出判断,开启熔断开关,拒绝流量访问,避免大流量对后端的过载请求。系统也应该能够动态监测后端程序的修复情况,
当程序已恢复稳定时,可以关闭熔断开关,恢复正常服务。 2.服务降级: 将系统的所有功能服务进行一个分级,当系统出现问题,需要紧急限流时,可将不是那么重要的功能进行降级处理,停止服务,这样可以释放出更多的资源供给核心功能的去用。 例如在电商平台中,如果突发流量激增,可临时将商品评论、积分等非核心功能进行降级,停止这些服务,释放出机器和CPU等资源来保障用户正常下单,而这些降级的功能服务可以等整个系统恢复正常后,再来启动,进行补单/补偿处理。 除了功能降级以外,还可以采用不直接操作数据库,而全部读缓存、写缓存的方式作为临时降级方案。 3.延迟处理: 这个模式需要在系统的前端设置一个流量缓冲池,将所有的请求全部缓冲进这个池子,不立即处理。然后后端真正的业务处理程序从这个池子中取出请求依次处理,常见的可以用队列模式来实现。这就相当于用异步的方式去减少了后端的处理压力,
但是当流量较大时,后端的处理能力有限,缓冲池里的请求可能处理不及时,会有一定程度延迟。 4.特权处理: 这个模式需要将用户进行分类,通过预设的分类,让系统优先处理需要高保障的用户群体,其它用户群的请求就会延迟处理或者直接不处理。
那在实际项目中,对访问流量的限制,可采用如下几种技术方法
1.熔断技术
熔断的技术可以参考Resilience4j的CircuitBreaker
2.计数器方法
系统维护一个计数器,来一个请求就加1,请求处理完成就减1,当计数器大于指定的阈值,就拒绝新的请求。基于这个简单的方法,可以再延伸出一些高级功能,比如阈值可以不是固定值,是动态调整的。
另外,还可以有多组计数器分别管理不同的服务,以保证互不影响等。
3.队列方法
就是基于FIFO队列,所有请求都进入队列,后端程序从队列中取出待处理的请求依次处理。基于队列的方法,也可以延伸出更多的玩法来,比如可以设置多个队列以配置不同的优先级。
4.令牌桶方法
首先还是要基于一个队列,请求放到队列里面。但除了队列以外,还要设置一个令牌桶,另外有一个脚本以持续恒定的速度往令牌桶里面放令牌,后端处理程序每处理一个请求就必须从桶里拿出一个令牌,
如果令牌拿完了,那就不能处理请求了。我们可以控制脚本放令牌的速度来达到控制后端处理的速度,以实现动态流控。
这篇博客有一些限流算法:https://www.cnblogs.com/hlkawa/p/13111003.html
2.2 服务限流的注意事项
2.2.1 服务限流时的需要注意的一些原则和事项
实时监控:系统必须要做好全链路的实时监控,才能保证限流的及时检测和处理。
手动开关:除系统自动限流以外,还需要有能手动控制的开关,以保证随时都可以人工介入。
限流的性能:限流的功能理论上是会在一定程度影响到业务正常性能的,因此需要做到限流的性能优化和控制。
2.2.2 限流算法分布式改造
相对于单机限流算法,分布式限流算法的是指: 算法可以分布式部署在多台机器上面,多台机器协同提供限流功能,可以对同一接口或者服务做限流。分布式限流算法相较于单机的限流算法,最大的区别就是接口请求计数器需要中心化存储,比如以Redis作为 中心计数器来实现分布式限流算法。分布式限流算法在引入 Redis 中心计数器这个独立的系统之后,系统的复杂度一下子高了很多,因为要解决一些分布式系统的共性技术问题:
1. 数据一致性问题接口限流过程包含三步操作: Step 1:“读”当前的接口访问计数n; Step 2:”判断”是否限流; Step 3:“写”接口计数 n+1, if 接口限流验证通过 在并发情况下,这3步CAS操作(compare and swap)存在race condition。在多线程环境下,可以通过线程的加锁或者concurrent开发包中的Atomic原子对象来实现。在分布式情况下,思路也是类似的,可以通过分布式锁,来保证同一时间段只有一个进程在访问,
但是引入分布式锁需要引入新的系统和维护锁的代码,代价较大,为了简单,我们可以选择另一种思路:借助Redis单线程工作模式 +Lua脚本完美的支持了上述操作的原子性。
对于Redis的各种异常情况,我们处理起来并不是很难,catch住,封装为统一的exception,向上抛,或者吞掉。但是如果Redis访问超时,会严重影响接口的响应时间甚至导致接口响应超时,这个副作用是不能接受的。
所以在我们访问Redis时需要设置合理的超时时间,一旦超时,判定为限流失效,继续执行接口逻辑。Redis访问超时时间的设置既不能太大也不能太小,太大可能会影响到接口的响应时间,太小可能会导致太多的限流失效。
我们可以通过压测或者线上监控,获取到Redis访问时间分布情况,再结合服务接口可以容忍的限流延迟时间,权衡设置一个较合理的超时时间。
分布式限流算法的性能瓶颈主要在中心计数器Redis,在没有做Redis sharding的情况下,基于单实例Redis的分布式限流算法的性能要远远低于基于内存的单机限流算法,此处需要进行压测看到具体参数。
所以在应用分布式限流算法时,一定要考量限流算法的性能是否满足应用场景,如果微服务接口的TPS已经超过了限流框架本身的TPS,则限流功能会成为性能瓶颈影响接口本身的性能。
除了TPS之外,网络延迟也是一个需要特别考虑的问题,特别是如果中心计数器与限流服务跨机房跨城市部署,之间的网络延迟将会非常大,严重影响微服务接口的响应时间。
2.2.3 选择单机限流还是分布式限流
首先需要说明一下:这里所说的单机限流和分布式限流与之前提到的单机限流算法和分布式限流算法并不是一个概念!为了提高服务的性能和可用性,微服务都会多实例集群部署,所谓单机限流是指:独立的对集群中的每台实例进行接口限流,比如限制每台实例接口访问的频率为最大 1000 次 / 秒,单机限流一般使用单机限流算法;所谓的分布式限流是指:提供服务级的限流,限制对微服务集群的访问频率,比如限制 A 调用方每分钟最多请求 1 万次“用户服务”,分布式限流既可以使用单机限流算法也可以使用分布式限流算法。
单机限流的初衷是防止突发流量压垮服务器,所以比较适合针对并发做限制。分布式限流适合做细粒度限流或者访问配额,不同的调用方对不同的接口执行不同的限流规则,所以比较适合针对 hits per second 限流。从保证系统可用性的角度来说,单机限流更具优势,从防止某调用方过度竞争服务资源来说,分布式限流更加适合。
分布式限流与微服务之间常见的部署架构有以下几种
1. 在接入层(api-gateway)集成限流功能 这种集成方式是在微服务架构下,有api-gateway的前提下,最合理的架构模式。如果api-gateway是单实例部署,使用单机限流算法即可。如果api-gateway是多实例部署,为了做到服务级别的限流就必须使用分布式限流算法。 2. 限流功能封装为RPC服务 当微服务接收到接口请求之后,会先通过限流服务暴露的RPC接口来查询接口请求是否超过限流阈值。这种架构模式,需要部署一个限流服务,增加了运维成本。这种部署架构,性能瓶颈会出现在微服务与限流服务之间的RPC通信上,
即便单机限流算法可以做到200万TPS,但经过RPC框架之后,做到10万TPS的请求限流就已经不错了。 3. 限流功能集成在微服务系统内 这种架构模式不需要再独立部署服务,减少了运维成本,但限流代码会跟业务代码有一些耦合,不过,可以将限流功能集成在切面层,尽量跟业务代码解耦。
如果做服务级的分布式限流,必须使用分布式限流算法,如果是针对每台微服务实例进行单机限流,使用单机限流算法就可以。
2.2.4 不同业务使用不同限流熔断策略
这里所讲的熔断策略,就是当接口达到限流上限之后,如何来处理接口请求的问题。前面也有提到过一些限流熔断策略了,所谓否决式限流就是超过最大允许访问频率之后就拒绝请求,比如返回 HTTP status code 429 等,所谓阻塞式限流就是超过最大允许访问频率之后就排队请求。除此之外,还有其他一些限流熔断策略,比如:记录日志,发送告警,服务降级等等。
同一个系统对于不同的调用方也有可能有不同的限流熔断策略,比如对响应时间敏感的调用方,我们可能采用直接拒绝的熔断策略,对于像后台 job 这样对响应时间不敏感的调用方,我们可能采用阻塞排队处理的熔断策略。
我们再来看下其他熔断策略的一些应用场景:比如限流功能刚刚上线,为了验证限流算法的有效性及其限流规则的合理性,确保不误杀请求,可以先采用日志记录 + 告警的限流熔断策略,通过分析日志判定限流功能正常工作后,再进一步升级为其他限流熔断策略。
不同的熔断策略对于选择限流算法也是有影响的,比如令牌桶和漏桶算法就比较适合阻塞式限流熔断场景,如果是否决式的限流熔断场景就比较适合选择基于时间窗口的限流算法。
2.2.5 不同层级的限流
限流的原则,是尽量在流量源头限,并且是需要依据现有团队所掌握的技能来。
slb节点的限流
slb全称 Service Load Balancer,slb的限流更准确的描述是拦截
slb流量特点
几乎来自外部的流量都从这个入口过来,无论是带业务属性的还是不带业务属性的、ddos的、正常流量、爬虫等统统从这里来。
需要拦截是什么(由于流量过了这个节点就是我们的应用系统了,因此最好是把非业务应用相关的流量挡住,限制住,让它有序进来,不要冲垮系统)
ddos攻击流量
其他通用级的不安全流量:sql注入、xss注入等
连接并发限制
每ip请求限流控制
爬虫流量
上述是slb节点,但是也有团队考虑到本身技能,以及代码git化存储的原则,会把某些配置往后面的nginx/kong移,因为slb的配置是UI界面化的,代码化存储比较不直接;但是nginx/kong这种就相对容易多了,而且恢复时只要脚本到位,分分钟就恢复一套系统,很方便。
nginx节点的流限的
到了这里,ddos这种攻击流量应该算是过滤掉了,常见的sql注入等攻击也过滤掉了;但是还存在爬虫流量(有时,这种流量是我们需要的,SEO推广等);也会包含高级攻击流量
因此nginx节点需要做的限流是(通用级别的限流)
爬虫限流、并发控制、或者过滤、又或者重定向到蜜罐系统(专门给爬虫做的系统,和主业务系统隔离)
每ip请求限流
spring cloud gateway节点的限流
到了这里,一般普通静态H5资源的访问已经没有了(已经重定向到其他nginx节点分流处理掉了);gateway处理的都是动态编程语言需要处理的流量,这里指java。
也就是说,到了这个节点,开始进入java系统领域,流量承受能力比nginx降了1个等级,需要做更多的限制
普通场景下的限流 突发流量下的限流,如:秒杀等 CC攻击+验签的过滤(由于公私钥证书一般加在java节点上,因此此处放java系统范畴,而不是slb之前,或者nginx之前) 可以在gateway动态路由中分别配置各自的限流配置,以及上述自定义的CC+验签配置
隔离性
由于gateway流量会转发给后端一大堆微服务,假设由于哪个java微服务处理不过来hang住了,又不想影响其他后端为服务的转发,因此需要做隔离性。
可选方案:
resilience4j
sentinel
guava
此处的限流和nginx的限流有啥区别?
nginx的阈值要大,因为nginx覆盖的范围不光是java领域,还有H5等其他范围
nginx的限流配置维度是通用的,但是spring cloud gateway就变化多了,可以通过自定义KeyResolver来决定所需要的维度来限流,如:用户id维度、ip维度、租户维度等,灵活度大了。
微服务节点的限流
到了这里,就是具体的微服务应用了,单个微服务所能承受的流量,做得好的话是能用jmeter测量出来的,可以通过这个值来参考设置。
再然后,到了具体服务中了,其实限流的维度就更多了,当然需要考量下是否需要加很多限流,脆弱敏感的服务就加些,比如计费等,或者用其他技术做限流,如:queue,然后固定住consumer数来消费,稳住速率。
所采用技术和gateway一样,也可以自己实现,实现难度都还好。
流量大的系统,最好是用特定技术把income请求根据不同的维度划分好独立的线程池,不要相互影响;由本服务发起的到其他服务的请求调用,也需要单独的线程池来处理。总之目标就是都独立,不互相影响,即便其他服务慢了,自己也不慢。
因此,熔断又出现了
当其他服务很慢,超时了,我方作为服务调用方不能被拖垮啊,这时,就断开吧,用个指定的协议响应暂且认定为服务不可用之类的,等后续再补偿回查。
当然关键服务是不能这么处理的,只能是辅助服务。关键服务就必须要jmeter压测提升性能。
-
核心服务的梳理
-
辅助服务熔断的返回值+应对方式
-
核心服务的压侧
2.2.6 配置合理的限流规则
限流规则包含三个部分:时间粒度,接口粒度,最大限流值。限流规则设置是否合理直接影响到限流是否合理有效。
对于限流时间粒度的选择,我们既可以选择1秒钟不超过1000次,也可以选择10毫秒不超过10次,还可以选择1分钟不超过6万次,虽然看起这几种限流规则都是等价的,但过大的时间粒度会达不到限流的效果,比如限制1分钟不超过6万次,就有可能6万次请求都集中在某一秒内;相反,过小的时间粒度会削足适履导致误杀很多本不应该限流的请求,因为接口访问在细时间粒度上随机性很大。所以,尽管越细的时间粒度限流整形效果越好,流量曲线越平滑,但也并不是越细越合适。
对于访问量巨大的接口限流,比如秒杀,双十一,这些场景下流量可能都集中在几秒内,TPS 会非常大,几万甚至几十万,需要选择相对小的限流时间粒度。相反,如果接口TPS很小,建议使用大一点的时间粒度,比如限制1分钟内接口的调用次数不超过1000 次,如果换算成:一秒钟不超过16次,这样的限制就有点不合理,即便一秒内超过16次,也并没有理由就拒绝接口请求,因为对于我们系统的处理能力来说,16次/秒的请求频率太微不足道了。即便1000次请求都集中在1分钟内的某一秒内,也并不会影响到系统的稳定性,所以1秒钟16次的限制意义不大。
除了时间粒度之外,还需要根据不同的限流需求选择不同接口粒度,比如:
1)限制微服务每个实例接口调用频率 2)限制微服务集群整体的访问频率 2)限制某个调用方对某个服务的调用频率 3)限制某个调用方对某个服务的某个接口的访问频率 4)限制某服务的某个接口的访问频率 5)限制某服务的某类接口的访问频率
对于最大允许访问频率的设置,需要结合性能压测数据、业务预期流量、线上监控数据来综合设置,最大允许访问频率不大于压测 TPS,不小于业务预期流量,并且参考线上监控数据。
在大促,秒杀,或者其他异常流量到来之前,我们需要事先通过实验来验证限流功能的有效性,用数据来证明限流功能确实能够拦截非预期的异常流量。否则,就有可能会因为限流算法的选择不够合适或者限流规则设置不合理,导致真正超预期流量到来的时候,限流不能起到保护服务的作用,超出预期的异常流量压垮系统。
如何测试限流功能正确有效呢?尽管可以通过模拟流量或者线上流量回放等手段来测试,但是最有效的测试方法还是:通过导流的方式将流量集中到一小组机器上做真实场景的测试。对于测试结果,我们至少需要记录每个请求的如下信息:对应接口,请求时间点,限流结果 (通过还是熔断),然后根据记录的数据绘制成如下图表:
从图表中,我们可以一目了然的了解限流前与限流后的流量情况,可以清晰的看到限流规则和算法对流量的整形是否合理有效。
除了事先验证之外,我们还需要时刻监控限流的工作情况,实时了解限流功能是否运行正常。一旦发生限流异常,能够在不重启服务的情况下,做到热更新限流配置:包括开启关闭限流功能,调整限流规则,更换限流算法等等。
3. 服务熔断的设计
在股票市场,熔断这个词大家都不陌生,是指当股指波幅达到某个点后,交易所为控制风险采取的暂停交易措施。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。
3.1 服务熔断和服务降级比较
两者其实从有些角度看是有一定的类似性的
1.目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段
2.最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用
3.粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改)
4.自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段
而两者的区别也是明显的:
1.触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑
2.管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)
3.实现方式不太一样
3.2 雪崩效应
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。
如果下图所示:a作为服务提供者,b为c的服务消费者,d和e是b的服务消费者。a不可用引起了b的不可用,并将不可用像滚雪球一样放大到d和e时,雪崩效应就形成了
3. 熔断器(CircuitBreaker)
熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。
熔断器开关相互转换的逻辑如下图