继续更新中,欢迎点赞关注!
这一片文章学习服务熔断,首先了解几个概念。(部分摘要,点击查看)
什么是断路器?
“断路器”本身是一种开关装置,当某个服务单元发生故障监控(类似熔断保险丝),向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延。乃至雪崩。
什么是熔断机制?
熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某一个微服务出错不可用或者响应时间太长,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息,当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务调用的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。
一、代码实现实例
修改我们上一篇文章新建的生产者cloud-provider-hystrix-payment8001的服务中的业务类PaymentService,这个paymentCircuitBreaker方法中的逻辑是传递一个参数id,当id<0时会抛出一个运行时的异常,否则就是满足条件,打印一个uuid。具体进行配置。如下图:
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少后跳闸 }) public String paymentCircuitBreaker( Integer id) { if(id < 0) { throw new RuntimeException("******id 不能负数"); } String serialNumber = IdUtil.simpleUUID(); return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber; } //兜底降级的方法 public String paymentCircuitBreaker_fallback(Integer id) { return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " +id; }
Hystrix断路器使用时最常用的三个重要指标参数
在微服务中使用Hystrix作为断路器时,通常涉及到以下三个重要的指标参数(这里是写在@HystrixProperties注解中,当然实际项目中可以全局配置在yml或properties中)
1、circuitBreaker.sleepWindowInMilliseconds
断路器的快照时间窗,也叫做窗口期。可以理解为一个触发断路器的周期时间值,默认为10秒(10000)。
2、circuitBreaker.requestVolumeThreshold
断路器的窗口期内触发断路的请求阈值,默认为20。换句话说,假如某个窗口期内的请求总数都不到该配置值,那么断路器连发生的资格都没有。断路器在该窗口期内将不会被打开。
3、circuitBreaker.errorThresholdPercentage
断路器的窗口期内能够容忍的错误百分比阈值,默认为50(也就是说默认容忍50%的错误率)。打个比方,假如一个窗口期内,发生了100次服务请求,其中50次出现了错误。在这样的情况下,断路器将会被打开。在该窗口期结束之前,即使第51次请求没有发生异常,也将被执行fallback逻辑。
综上所述,在以上三个参数缺省的情况下,Hystrix断路器触发的默认策略为:
在10秒内,发生20次以上的请求时,假如错误率达到50%以上,则断路器将被打开。(当一个窗口期过去的时候,断路器将变成半开(HALF-OPEN)状态,如果这时候发生的请求正常,则关闭,否则又打开)
然后在控制层进行调用,如下图:
@GetMapping("/payment/circuit/{id}") public String paymentCircuitBreaker(@PathVariable("id") Integer id) { String result = paymentService.paymentCircuitBreaker(id); log.info("****result: "+result); return result; }
启动Eureka7001服务和该8001服务,然后访问http://localhost:8001/payment/circuit/1,传递的参数id是1,大于0,所以会返回流水号uuid。如下图:
然后我们将参数id传递一个负数的,进行访问http://localhost:8001/payment/circuit/-1, 就会返回运行时的异常的提示。如下图:
接下来我们就进行测试,由于上边的配置是在10秒内,访问10次,如果超过6次错误,就会打开我们的断路器,打开断路器就是我们传递正确的参数,也不成功返回流水号uuid。如下图:
这就说明断路器打开了,然后随着时间增加和我们正确的访问,容错率变低,就慢慢恢复了,断路器的状态变为了半开状态,随着正确率的提高,会自动关闭。就可以正确访问了, 如下图:
熔断三大类型:
熔断打开:请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。 熔断关闭:熔断关闭不会对服务进行熔断。 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则认为当前服务恢复正常,关闭熔断。
断路器开启或者关闭的条件有哪些?
1、当满足一定的阈值的时候(默认10秒钟超过20个请求次数)
2、当失败率达到一定的时候(默认10秒钟超过50%的请求次数)
3、当达到以上阈值,断路器将会开启
4、当开启的时候,所有请求都不会进行转发
5、一段时间之后(默认5秒),这个时候断路器是半开状态,会让其他一个请求进行转发
6、如果成功,断路器会关闭,若失败,继续开启重复第4步和第5步
断路器打开之后会发生什么?
1、再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。
2、原来的主逻辑要如何恢复呢?
对于这一问题,Hystrix也为我们实现了自动恢复功能,当断路器打开,对主逻辑进行熔断之后,Hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑。当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。
Hystrix工作流程
官网的的流程图描述了Hystrix的工作流程:
1、每次调用都会创建一个HystrixCommand 2、执行execute或queue做同步\异步调用 3、判断熔断器是否打开,如果打开跳到步骤8,否则进入步骤4 4、判断线程池/信号量是否跑满,如果跑满进入步骤8,否则进入步骤5 5、调用HystrixCommand的run方法,如果调用超时进入步骤8 6、判断是否调用成功,返回成功调用结果,如果失败进入步骤8 7、计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态 8、降级处理逻辑,根据上方的步骤可以得出以下四种情况会进入降级处理:熔断器打开、线程池/信号量跑满、调用超时、调用失、 9、返回执行成功结果
Hystrix的服务熔断大概就学习到这里啦,也是so easy!
下一篇文章将继续学习Hystrix的图形化Dashboard实时监控,文章持续更新,欢迎关注!