文章目录
Hystrix断路器
整体思维导图
服务雪崩概述
分布式系统面临的问题?
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败,依赖关系如下图:
上图图中的请求需要调用A,P, H,I四个服务,如果一切顺利则没有什么问题,关键是如果I服务超时或者无响应会出现什么情况呢?
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。所以,通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。
Hystrix是什么
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间,不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
hystrix案例
Hystrix支付微服务的构建
新建cloud-provider-hystrix-payment8001
POM
YML
主启动
业务类
首先写service层,如下图:
然后写controller层,如下图:
正常测试
启动Eureka7001/7002,启动HystrixPayment8001如下图:
然后去Eureka注册中心里面查看,如下图:
去测试控制器中的两个接口,如下图:
高并发测试
对于上面的正常测试,测试localhost:8001/payment/hystrix/ok/31接口的时候非常快,上面的刷新图标不需要转圈圈;但是测试localhost:8001/payment/hystrix/timeout/31这个接口的时候,因为需要等待3秒,所以上面的刷新图标会转圈圈。
现在我们来一个Jmeter压测测试,就是我们测试了同时有20000人访问等待3秒的这个接口,看它抗不抗的住,然后我们又去测试了一下无需等待的这个接口localhost:8001/payment/hystrix/ok/31,此时发现这个接口也需要等待了,上面的刷新图标会停顿很久,已经不是秒跳了,为什么会这样呢?因为tomcat的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。上面还是服务提供者8001自己测试,假如此时外部的消费者80也来访问,那消费者只能干等,最终导致消费端80不满意,服务端8001直接被拖死。
消费者80服务
新建cloud-consumer-feign-hystrix-order80
POM
如下图:
YML
主启动
业务类
先写service远程服务动态代理接口,如下图:
然后写控制器,如下图:
正常测试
先启动Eureka7001/7002,再启动hystrix-payment8001,最后启动消费者80服务,如下图:
然后在浏览器中访问消费者服务的接口,如下图:
正常测试是可以测试的。
高并发测试
在上面的正常测试中,消费者服务是可以正常的访问提供者服务的额,但是在高并发测试中并不是这样的。比如,我们在Jmeter中进行压测测试,同时用2W个请求访问提供者服务,那么这个时候提供者服务就会抗不住,因为没Tomcat中有足够多的线程去处理外界压力和请求了,所以如果你这个时候再去用消费者服务调提供者服务就会出现问题,要么浏览器一直在转圈圈如下图:
要么会出现超时异常。
上诉高并发测试异常结论
正因为有上述故障或不佳表现,才有我们的降级/容错/限流等技术诞生。
如何解决?解决的要求
消费者服务访问提供者服务,如果提供者服务超时了,提供者服务不能卡死等待,必须要有降级;
消费者服务访问提供者服务,如果提供者服务down机了,那么消费者服务不能卡死等待,必须要有降级;
提供者服务OK,消费者服务自己出故障或有自我要求(自己的等待时间小于服务提供者),那么需要消费者自己处理降级
服务降级
提供者8001服务先从自身找问题进行fallback服务降级
在主启动类上加上一个@EnableCircuitBreaker注解,如下图:
在提供者服务的对应的方法中加上对应的降级标准,包括超时多长时间会降级,以及降级之后会用到哪一个方法,如下图:
上面的这个图片中,@HystrixProperty注解中的value="3000"的意思表示的是,如果paymentInfo_TimeOut方法执行的时间超过了3秒,那么会自动进行降级访问paymentInfo_TimeOutHandler方法。
消费者80服务进行fallback服务降级
改YML
这样使用feign进行远程服务动态代理接口调用另外一个微服务的时候,才支持使用服务降级,如果feign.hystrix.enabled的值为false,那么消费者服务是不支持服务降级的。并且如果想要让消费者服务使用feign的时候支持服务降级,那么还必须要在主启动类上加上一个@EnableHystrix注解。
改主启动
在主启动类上加上@EnableHystrix注解,如下图:
加上一个@EnableHystrix注解之后,这样消费者服务使用feign远程服务动态代理接口的时候,才会支持hystrix的服务降级,要不然消费者没办法在使用feign的时候进行服务降级。
改业务类
测试
启动Eureka7001/7002服务,然后启动提供者服务8001,接着启动消费者服务80,如下图:
然后访问消费者服务,如下图:
从上图可以看出,消费者服务已经进行服务降级了,因为本来访问的是paymentInfo_TimeOut方法,但是因为消费者只能等待1.5s,而提供者服务的paymentInfo_TimeOut方法需要3s才能执行完毕,所以消费者会自动进行服务降级,不再等待,而是直接访问消费者服务的paymentTimeOutFallbackMethod方法。并且如果paymentInfo_TimeOut方法中出现了运行异常比如遇见了类似于10/0这样的语句,那么消费者服务会自动进行服务降级,去访问paymentTimeOutFallbackMethod方法。
Hystrix之全局服务降级DefalutProperties
目前问题
每个业务方法对应一个兜底的方法,代码膨胀;统一和自定义分开。
@DefaultProperties(defaultFallback="")
1:1每个方法配置一个服务降级方法,技术上可以,实际上傻X
1:N除了个别重要核心业务有专属,其它普通的可以通过@DefaultProperties(defaultFallback="")统一跳转到统一处理结果页面。
通用的和独享的各自分开,避免了代码膨胀,合理减少了代码量.
如何实现Hystrix的全局服务降级
首先需要有一个兜底的全局服务降级的方法,如下图:
接着需要在控制器上加一个@DefaultProperties(defaultFallback="")的注解,如下图:
最后给需要降级的方法加上一个@HystrixCommand注解,但是不必给注解的属性赋值,表示这个方法没有指定的服务降级的方法,这个方法将会使用全局的服务降级的方法;如果要是给@HystrixCommand注解的属性赋值那么表示的是会用到指定的服务降级方法,而不会使用到默认的服务降级方法。加上一个@HystrixCommand注解如下图:
Hystrix之通配服务降级FeignFallback
首先配置一个服务降级的通用类,这个类需要实现远程服务动态代理接口,这个类里面实现的方法就是远程服务动态代理接口中的方法对应的服务降级方法,如下图:
然后在配置文件里面增加对feign对hystrix服务降级的支持并且也需要在主启动类加上@EnabledHystrix注解开启feign对于hystrix服务降级的支持,如下图:
最后在远程服务动态代理接口中引入这个服务降级的通用配置类,如下图:
易错点,如下图:
测试
首先开启Eureka7001/7002,8001,80服务如下图:
然后通过消费者访问提供者的ok服务,如下图:
假如这个时候提供者服务down机了,那么这个时候消费者服务会自动的根据自己的通用的服务降级类,进行服务降级,8001提供者宕机后的访问如下图:
服务熔断
概念
在一定的时间内,如果错误率达到某个值的时候就会自动的熔断该微服务方法,那么下次即便是调用正确,也仍然会发生服务降级,这就叫做服务熔断。注意服务熔断后也会发生服务降级。
熔断机制概述:
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,默认是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand
例子
主启动类加上一个注解,如下图:
在service业务方法中进行配置,如下图:
上图中的@HystrixProperty中涉及到断路器的三个重要参数:快照时间窗口,请求总数阈值,错误百分比阈值。
1.快照时间窗口:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗口,默认为最近的10秒。
2.请求总数阈值:在快照时间窗口内,必须满足请求总数阈值才有资格熔断。默认是20,一位置在10s内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
3.错误百分比阈值:当请求总数在框照时间窗口内超过了阈值,比如发生了30次调用,如果这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阈值情况下,这时候就会将断路器打开。
在控制器中调用service中的方法,写一个调用接口,如下图:
测试
首先疯狂刷新错误请求,如下图:
疯狂刷新错误请求之后,进行正确请求的访问,如下图:
隔一段时间,或者是正确率上升之后(也即是不该发生服务降级的请求次数变多之后),服务熔断就会消失,微服务恢复正常,这个时候我们发送本不该发生服务降级的请求的时候就不会发生服务降级了,如下图:
服务限流
后面高级篇讲解alibaba的Sentinel说明。
服务监控hystrixDashboard
概述
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
仪表盘9001
新建cloud-consumer-hystrix-dashboard9001
POM
YML
HystrixDashboardMain9001主启动类
主启动类上必须要新加注解@EnableHystrixDashboard,如下图:
所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置
启动cloud-consumer-hystrix-dashboard9001该微服务后续将监控微服务8001
测试
去浏览器访问地址:localhost:9001/hystrix,如下图:
使用hystrixDashboard服务监控,监控8001提供者服务的服务熔断情况
提供者服务8001中需要的配置
首先提供者服务的pom文件里面必须要加上web依赖和actuator依赖,如下图:
然后提供者服务的主启动类上一定要加上支持服务熔断的注解,如下图:
最后提供者服务的主启动类里面一定要加上一个配置,如下图:
不加上述配置会出现的错误,如下图:
启动所需的微服务
启动Eureka7001/7002,8001,9001微服务,如下图:
测试图形化监控器的效果
去浏览器中输入9001微服务HystrixDashboard所对应的而图形化监视页面对应的地址localhost:9001/hystrix,如下图:
然后点击Monitor Stream按钮,进行图形化监视提供者服务8001对应的服务熔断的情况,如下图:
试着往提供者服务一直发送成功的请求(就是不会进行服务降级的请求),看看图形化监测页面的变化,如下图:
然后再往提供者服务一直发送错误的请求(就是会进行服务降级的请求),看看图形化监测页面的变化,如下图: