断路器
断路器
现在微服务架构当中,服务一般都是越来越多的,那么,如果出了异常,抛出错误,如果没有进行很好的处理,一般都是很难看的,而且,由于一些错误的产生可能条件很不确定,那么,要优雅的处理这些错误一定是很麻烦的。所以,现在出现了断路器的概念。
什么是断路器?
如同电路断路器,保险丝一样的东西,如果出现用电功率突然增加,那么保险丝就会断了,用来保护电路,确定没问题了之后,更换保险丝,电路重新恢复正常。就如同我们的某段代码出现异常,那么断路器就会执行,就不会对错误的代码进行再次调用了。软件方面的断路器,严格来说就是一个后备程序。
软件断路器
被保护的程序在给定的阀值内出现了异常,那么就可以调用一个后备方法,断路器就处于打开的状态了,以后请求就都会走这个后备方法。如果是暂时性的问题,比如网络问题,过一段时间,网络恢复了,断路器就会偶尔再去请求之前的错误方法,这个时候的状态被称为半开状态,如果方法没问题了,那么,断路器就会关闭,程序正常执行,如果依然失败,就还是开启状态。
断路器的本质
通过代码的层面来看,断路器就如同一个大型的try…catch…,try里面执行代码,catch执行后备操作,但是,断路器是更加智能的,频繁失败的方法,它就会跳过程序,执行进行后备操作。
断路器的应用
一般情况下,断路器都会用在以下场景:
- 远程请求:RestTemplate为代表的远程请求,请求失败或者耗时很长却并不能一定获取到正确的返回结果
- 数据库查询:作为暂时性处理,作为标记后续需要处理的慢查询问题,不能依赖断路器
- 可能比较慢的方法:不一定失败,但是耗时长的任务
微服务中,某个执行缓慢的微服务不能拖慢整个微服务的性能,避免上游的服务产生联级延迟是要避免的。
Hystrix
Netflix Hystrix是断路器模式的Java实现。Hystrix断路器实现了一个切面,会在目标发生失败的时候执行后备方法。为了实现断路器模式,这个切面还会跟踪目标方法的失败频率,如果他超过了设定的某个阀值,就会触发断路的功能,执行后备方法,反之,就会关闭断路,让方法正常执行。
使用Hystrix
引入依赖
1 | <dependency> |
启用注解
1 |
|
在对应的方法上使用@HystrixCommand注解,并定义对应的后备方法,如果在使用该方法时出现异常,那么就会去调用后备方法
1 |
|
实际上,我们可以堆积任意数量的后备方法,但是,还是需要提供一个一定成功的方法,这个方法不需要使用断路器
HystrixCommand相关配置
注解@HystrixCommand可以通过的它的属性commandProperties和注解@HystrixProperty来配置相关的使用规则
缓解延时:Hystrix默认是1s的延时,请求超过这个时间,那么就会执行备用方法,可以通过配置来修改
1 |
|
阀值:默认情况下,会保护方法执行20次,而且50%以上的调用在10s之上时,断路器就会进入打开,后续调用就会执行后备方法,之后5s就会进入半打开状态,再次尝试原来的方法。
我们可以调整以上的相关属性,配置如下:
- circuitBreaker.requestVolumeThreshold:在给定时间内,方法被调用的次数
- circuitBreaker.errorThresholdPercentage:在给定时间内,方法调用产生失败的百分比
- metrics.rollingStats.timeoutInMillisecond:控制请求量和错误百分比的滚动时间周期,也就是设置给定时间
- circuitBreaker.WindowInMillisecond:开大状态下,多久进入半打开状态。半打开状态下,多久去主动尝试原始方法
1
2
3
4
5
6
7
8// 例如:20秒内调用超过30次而且失败率达到25%的方法进入打开状态
public Order getOrders();
Hystrix流
当调用保护方法时,就会收集一些信息,并将其发送到一个HTTP流中,这些数据可以监控正在运行中的应用的健康状态。Hystrix六中包含如下数据:
- 方法被调用多少次
- 调用成功了多少次
- 后备方法调用了多少次
- 方法超时了多少次
Hystrix流是由Actuator提供的,如果使用就需要引入相关依赖,SpringBoot也对其进行了支持,依赖如下:
1 | <dependency> |
收集到了流,那么就需要来展示它,同时,Netflix也提供了Hystrix的Dashboard,我们只需要引入相关依赖就可以
1 | <dependency> |
同时,需要加入开启Dashboard的注解@EnableHystrixDashboard
1 |
|
加号相关依赖和配置后,就可以访问Dashboard:http://localhost:7879/hystrix 来查看。
hystrix的线程模型
多个执行很慢的请求,hystrix都会进行阻塞,如果它们来自同一个线程池,线程池耗尽了,那么其他的请求就进不来了,所以,为了避免这种情况,hystrix自己维护了一个线程池,来处理这些请求。
hystrix为每项依赖都分配了一个线程池,当hystrix来调用时,就由自己去线程池中的某个线程执行,与调用线程就行隔离,执行时间长的话,就能够允许调用线程不会一直等待,线程耗尽也只会在hystrix托管的线程池中发送。
聚合多个Hystrix流
一个dashboard一次只能监控一个hystrix流,一般情况下,肯定会有多个服务,多个流,那么我们就需要再引入Netflix的Turbine项目,来组合多个流,把它们放在同一个dashboard中。
添加依赖:
1 | <dependency> |
注解:@EnableTurbine
1 |
|
如果不想所有的服务都展示,可以通过配置,来选择展示哪些应用
1 | turbine: |
