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;
}

测试

  • 启动 70018001
  • 访问 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部分请求执行业务逻辑,尝试恢复微服务,如果请求成功且符合规则,则关闭熔断