服务降级 / 服务熔断 / 服务限流
接上一篇:https://www.tinstu.com/2245.html
1.服务降级
不管是在消费者,还是提供者,都可以进行服务降级,使用过@HystrixCommand注解指定降级后的方法
一般服务降级 是放在 客户端
1.1服务降级-8001生产者服务端
cloud-provider-hystrix-payment8001
8001设置自身调用超时时间的峰值,峰值内可以正常运行。超过了就需要有兜底的方法,做服务降级fallback。向调用方法返回一个符合预期的,可以处理的备选响应(FallBack)
1.1.1业务类(Service)方法上添加@HystrixCommand
service 添加
一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand
标注好的fallbackMethod
调用类中的指定方法,当前服务不可用了,做服务降级,兜底的方案都是paymentInfo_TimeOutHandler。

1.1.2主启动类激活
主启动类添加新注解@EnableCircuitBreaker
1.1.3测试

1.2服务降级-80消费者服务端(客户端)
cloud-consumer-feign-hystrix-order80
1.2.1修改yaml
1.2.2主启动类:@EnableHystrix
1.2.3业务类——Controller
Controller
1.2.4测试
因为80设置的1500得不到响应就执行fallbackmethod,而8001设置的3000ms 再进行返回,
所以,访问:http://127.0.0.1/consumer/payment/hystrix/timeout/1

1.3进一步优化
1.3.1 问题
目前存在的问题——代码臃肿、耦合度高
- 我们现在服务降级的方法和业务处理的方法混杂在了一块,耦合度很高。
- 如果每个接口,每个方法都需要一个“兜底”方法,那么就会造成代码臃肿
1.3.2 全局服务降级 DefaultProperties
所以我们需要一个全局的服务降级:global fallback;需要特殊照顾的方法,我们再进行精确的配置服务降级
1:N 除了个别重要核心业务有专属,其它普通的可以通过@DefaultProperties(defaultFallback = "")
统一跳转到统一处理结果页面
通用的和独享的各自分开,避免了代码膨胀,合理减少了代码量。
——————————————-
下面以消费者服务端80为例:cloud-consumer-feign-hystrix-order80
- 在业务类Controller上加@DefaultProperties(defaultFallback = “method_name”)注解,并指明defaultFallback
- 在需要服务降级的方法上标注@HystrixCommand 注解
- 如果@HystrixCommand里没有指明fallbackMethod,就默认使用@DefaultProperties(defaultFallback = “method_name”)中指明的降级服务

1.3.3通配服务降级 FeignFallback
在80微服务中,它没有注册进eureka注册中心成为eureka客户端。
而是通过openFeign,成为一个Feign客户端,通过Feign来进行微服务的调用和负载均衡。

直接定义Service层的接口通过@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
这个注解找CLOUD-PROVIDER-HYSTRIX-PAYMENT这个微服务中的方法进行调用。

解耦案例——服务降级:客户端调用服务端,遇到服务端宕机或关闭等极端情况
根据cloud-consumer-feign-hystrix-order80已经有的PaymentHystrixService接口,重新新建一个类(PaymentFallbackService)实现该接口,统一为接口里面的方法进行异常处理。
PaymentFallbackService
修改PaymentHystrixService接口,指定其服务异常处理类:
确认yml配置文件中开启了hystrix
目的是为了实现以下效果:
- 正常运行的话就找指定的微服务中的方法执行;
- 异常的话就找PaymentFallbackService,由它来统一进行服务降级的处理
这样的话客户端的OrderHystirxController中就不需要再进行降级处理,降级处理只针对要调用的微服务,因此降低了服务降级和客户端的耦合度。

2.服务熔断
2.1熔断机制概述
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,自动恢复调用链路。 熔断状态: 开启 关闭 半开启
大神论文:https://martinfowler.com/bliki/CircuitBreaker.html
半开状态: 比如说一个微服能承受100的并发量,某一时刻有500人同时访问。该服务就会崩掉,熔断,直接当掉。 外部此时不能访问了,过了一会,发现没有那么高的并发量了。感觉并发量在我的承受之内了(100)。 比如1s/72次,那么就试着这放开这些并发请求。 放着放着发现能够适应当前的并发量了,我再把闸道合上。 放着放着的状态就是半开状态,然后再把断路器关闭变成关闭的状态。
2.1.1对8001服务端service进行改造,开启熔断机制
paymentCircuitBreak
2.1.2修改模块cloud-provider-hystrix-payment8001的controller层
paymentCircuitBreaker
2.1.3测试
正常测试,启动7001,8001

测试熔断机制
在时间窗口期10s内,异常访问60%以上,发生断路,即正常也无法访问!

过一会刷新恢复正常!!!
2.2Hystrix服务熔断总结
2.2.1熔断类型
- 熔断打开:请求不再进行调用当前服务,再有请求调用时将不会调用主逻辑,而是直接调用降级fallback。实现了自动的发现错误并将降级逻辑切换为主逻辑,减少响应延迟效果。内部设置时钟一般为MTTR(Mean time to repair,平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。
- 熔断关闭:熔断关闭不会对服务进行熔断,服务正常调用
- 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断

2.2.2断路器在什么情况下开始起作用

涉及到断路器的四个重要参数:快照时间窗、请求总数阀值、窗口睡眠时间、错误百分比阀值。
- 1:快照时间窗(滚动窗口):断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
- 对应红框中的metrics.rollingStats.timeInMilliseconds
- 2:请求总数阀值:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
- 对应红框中的circuitBreaker.requestVolumeThreshold
- 3:窗口睡眠时间:剩下一个表示窗口睡眠时间,即断路器触发多少秒(默认5s)后尝试恢复,进入半开状态。
- 对应红框中的circuitBreaker.sleepWindowInMilliseconds
- 4:错误百分比阀值:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开。
- 对应红框中的circuitBreaker.errorThresholdPercentage
2.2.3断路器开启或关闭条件
1、当满足一定的阈值的时候(默认10秒内超过20个请求次数);
2、当失败率达到一定的时候(默认10秒内超过50%的请求失败);
3、到达以上阈值,断路器将会开启;
4、当开启的时候,所有请求都不会进行转发;
5、一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发;如果成功,断路器会关闭,若失败,继续开启。重复4和5。
2.2.4 断路器打开之后
1: 再有请求调用的时候,还会调用主逻辑吗?
将不会调用主逻辑,而是直接调用降级的fallback方法,通过断路器,实现了自动的发现错误并将降级逻辑升级为主逻辑,减少响应延迟的效果。
2:原来的主逻辑要如何恢复?
- 对于这一问题mhystrix也为我们实现了自动恢复功能。
- 当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑。
- 当休眠时间窗到期,断路器将进入半开状态,释放给一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合。
- 主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。
2.2.5所有的配置
hystrix所有配置
服务限流
在spring cloud alibaba Sentinel时再说!