一。基本概念
1.什么是服务熔断?
我们可以参照Martin Fowler于2014年6月份发表的有关于断路器的论文:https://martinfowler.com/bliki/CircuitBreaker.html
上面对于服务熔断的解释是这样的,这个简单的断路器避免了在电路断开时发出受保护的呼叫,但是当情况恢复正常时,将需要外部干预以将其重置。对于建筑物中的电路断路器,这是一种合理的方法,但是对于软件断路器,我们可以让断路器本身检测基础调用是否再次正常工作。我们可以通过在适当的时间间隔后再次尝试受保护的调用来实现这种自重置行为,并在成功后重置断路器。
2.结构图
分析:
从上图分析我们可以发现,在服务熔断中,断路器被分成了三种不同的状态:Closed
(关闭状态)、Open
(开启状态)以及Half Open
(半开状态)。相比于服务降级,服务熔断多了Half Open半开状态,使得服务有一个恢复链路的过程。
举个例子,当我们使用大功率电器从而导致保险丝熔断跳闸时,就会发生停电,家里面的电器都会因为没有电不能进行使用,这就相当于服务熔断,只有当我们重新更换保险丝开启电闸时,才能恢复供电,电器也得以使用,我们更换保险丝到恢复供电的这个过程就相当于链路的恢复过程。
二。实现过程
1.代码
消费端控制器接口代码:
//--------------服务熔断
@RequestMapping("ConsumerCircuitBreaker")
@HystrixCommand(fallbackMethod = "CircuitBreakerBack",commandProperties = {
//开启熔断器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
//10秒内十次请求有%60发生错误则开启熔断
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
public String ConsumerCircuitBreaker(@RequestParam("id") int id){
if(id<0){
throw new RuntimeException("id 不能为 负数");
}
//生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
//String uuid = IdUtil.randomUUID();
//生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();
return "调用成功,流水号为: "+simpleUUID;
}
//熔断降级调用方法
public String CircuitBreakerBack(@RequestParam("id") int id){
return "id 不能为负数,请稍后再试!!!";
}
涉及到断路器的三个重要参数:
快照时间窗
:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。请求总数阀值
:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,以为这在10秒内,如果该Hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。错误百分比阀值
:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过了50%的错误百分比,在默认设定50%的阀值情况下,这时候就会将断路器打开。
2.Hutool工具包
以上uuid的生成是使用到了hutool工具包来生成的,生成的uuid是唯一的且不带“-”的字符串
在pom.xml文件中导入相关依赖即可使用:
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.5</version>
</dependency>
Hutool工具包的使用请参考文档:https://www.hutool.cn/docs/#/
3.测试
单次访问,且id为正数:
单次访问,且id为负数:
先以id为负数的条件多次访问,再以id为正数的条件访问:
发现一个奇怪的现象:为什么我id明明是正数,却还是调用了降级方法呢?
这就是熔断器的链路服务恢复过程了,由此我们可以得出以下结论:
熔断打开
:请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开长达导致所设时钟则进入半熔断状态熔断关闭
:熔断关闭后不会对服务进行熔断熔断半开
:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断