Version: Next
服务熔断
达到最大服务访问后,直接拒绝访问
- 调用
服务降级
方法,返回友好提示
熔断机制
- 熔断机制 是应对 雪崩效应 的一种微服务链路保护机制
- 当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务降级
- 进而熔断该节点微服务的调用,快速返回错误的响应信息(就是直接跳过业务代码,不执行了,直接跑到降级兜底方法)
- 当检测到该节点的微服务调用响应正常后,恢复调用链路
- 由 Martin Fowler 提出:Circuit Breaker
SpringCloud 熔断机制
SpringCloud
熔断由Hystrix
实现Hystrix
会监控微服务间调用状况
- 当失败的调用达到一定阈值,默认是
5
秒内20
次调用失败,就是启动熔断机制
- 熔断机制的注解是
@HystrixCommand
实现—— provider-hystrix-payment8001
在
cloud-provider-hystrix-payment8001
的基础上修改
- 断路器属性:定义在
HystrixCommandProperties
中
属性 含义 circuitBreaker.enabled
是否开启断路器 circuitBreaker.requestVolumeThreshold
设置在一个 滚动窗口
中,打开断路器的最少请求数。circuitBreaker.sleepWindowInMilliseconds
熔断后尝试恢复的间隔时间 circuitBreaker.errorThresholdPercentage
错误率达到多少跳闸 metrics.rollingStats.timeInMilliseconds
设置统计的 滚动窗口
的时间
段大小
。该属性是线程池保持指标时间长短。
默认10000
也即10
秒
- 修改
ServiceImpl
类,添加服务熔断方法
10
次请求有60%
即6
次失败- 则触发熔断,休眠
10000
毫秒即10
秒后开始尝试恢复// ------ 服务熔断 ------ ------ 服务熔断 ------ ------ 服务熔断 ------ ------ 服务熔断 ------@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(@PathVariable("id") Integer id) {if (id < 0) {throw new RuntimeException("****id 不能为负数");}String serialNumber = IdUtil.simpleUUID();return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;}public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {return "id 不能为负数,请稍后再试, o(╥﹏╥)o id: " + id;}
- 修改
Controller
类
- 写一个对外暴露的服务接口,调用我们刚才在服务层定义好的代服务熔断的方法
- 报错是因为
service interface
没声明paymentCircuitBreaker(Integer id)
方法,去声明一下,略// ------ 服务熔断 ------ ------ 服务熔断 ------ ------ 服务熔断 ------ ------ 服务熔断 ------@GetMapping("/payment/circuit/{id}")public String paymentCircuitBreaker(@PathVariable("id") Integer id) {String result = paymentService.paymentCircuitBreaker(id);log.info("*****result: " + result);return result;}
测试
- 启动
7001
、8001
- 访问
localhost:8001/payment/circuit/{id}
{id}
为正数:正常响应一个 UUID{id}
为负数:算作一次失败,会触发服务降级执行兜底方法,打出id不能为负数,稍后再试
- 疯狂传负数,达到我们设定的熔断条件,就会触发熔断
- 触发熔断后:传
正数
也不会响应,因为熔断了
- 正数ID:
http://127.0.0.1:8001/payment/circuit/2
- 响应
hystrix-PaymentServiceImpl-1 调用成功,流水号:70f37afbb71e41c58dbb546977b59972
- 负数ID:
http://127.0.0.1:8001/payment/circuit/-1
- 响应:
id 不能为负数,请稍后再试, o(╥﹏╥)o id: -1
- 疯狂传负数,起码6次以上,然后传一个正数
- 响应:
id 不能为负数,请稍后再试, o(╥﹏╥)o id: 2
- 可以看到已经熔断了,传了个正数
2
上去服务依然跑了降级方法- 等待 10 秒以上,再传正数
- 响应:
hystrix-PaymentServiceImpl-10 调用成功,流水号:c83483db5b4b44cbbf1cac7152185276
- 可以看到服务成功恢复了
熔断状态
状态 | 含义 |
---|---|
熔断打开 OPEN | 请求到达后,不再执行业务逻辑,内部设置时钟,值为平均故障处理时间 熔断打开状态持续到该时钟设定值后,进入熔断半开状态 |
熔断关闭 CLOSED | 熔断关闭,不对微服务进行熔断 |
熔断半开 HALF-OPEN | 部分请求执行业务逻辑,尝试恢复微服务,如果请求成功且符合规则,则关闭熔断 |