熔断器 Hystrix

服务雪崩

假设存在如下调用链:

在这里插入图片描述
而此时,Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。
此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示

如上图所示,一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩。

那么,服务熔断和服务降级就可以视为解决服务雪崩的手段之一。

服务熔断

当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。Hystrix默认的超时时间为1s,请求时间超过1s,熔断次数加1。

熔断器机制:

  • closed:请求正常时,不使用熔断器;
  • open:统计请求的失败比例,达到阀值时,打开熔断器,请求被降级处理;延时一段时候后(默认休眠时间是5S)会进入halfopen状态;默认失败比例阀值是50%,请求次数最少不低于20次,例如:一段时间内请求30次,有20失败,熔断器将会打开,默认5s内的请求都会失败,直接返回。
  • halfopen:在进入该状态后会放入部分请求;判断请求是否成功,不成功,进入open状态,重新计时;成功,进入closed状态
  • 在这里插入图片描述

服务降级

服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。

服务熔断和服务降级的异同

相同点:

  • 目标一致 都是从可用性和可靠性出发,为了防止系统崩溃;
  • 用户体验类似 最终都让用户体验到的是某些功能暂时不可用;
    不同点:
  • 触发原因不同 服务熔断一般是某个服务(下游服务)故障引起
  • 而服务降级一般是从整体负荷考虑;

Hystrix

Hystris 是一个处理分布式系统的 延迟 和 容错 的开源库,在服务调用中不可避免的会调用失败,比如超时、异常等,Hystris 能够保证在一个服务出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性

Hystrix工作流程:

在这里插入图片描述
Hystrix整个工作流如下:

  • 构造一个
    HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;

  • 执行命令,Hystrix提供了4种执行命令的方法,后面详述;

  • 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响 - 应请求。Hystrix支持请求缓存,但需要用户自定义启动;

  • 判断熔断器是否打开,如果打开,跳到第8步;

  • 判断线程池/队列/信号量是否已满,已满则跳到第8步;

  • 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
    -统计熔断器监控指标;

  • 走Fallback备用逻辑

  • 返回请求响应
    从流程图上可知道,第5步线程池/队列/信号量已满时,还会执行第7步逻辑,更新熔断器统计信息,而第6步无论成功与否,都会更新熔断器统计信息。

服务降级配置

依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

启动类

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker//添加@EnableCircuitBreaker 或者 @EnableHystrix注解(可以使用@SpringCloudApplication代替多个注解)
public class OpenFeginMain {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeginMain.class,args);
    }
}
  • 单独回调方法的配置
    @HystrixCommand(fallbackMethod = "fallbackFun",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    @GetMapping("/to")
    public String to(){
        try {
            Thread.sleep(4000);
            log.info("to......................");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "sleep 4s..........";
    }
    public String fallbackFun(){
        return "fallbackFun...........";
    }
  • 全局默认回调的配置
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "defaultFallback")
public class OpenFeignController {
    
    @HystrixCommand
    @GetMapping("/test")
    public String test(){
        log.info("test......................");
        int i=0;
        return "test................";
    }

    public String fallbackFun(){
        return "fallbackFun...........";
    }
}
  • openFeign搭配Hystrix

application.yml

feign:
  hystrix:
    enabled: true

FeignService接口

@FeignClient(value = "Payment-Service",fallback = PaymentFallbackService.class)
@Component
public interface PaymentFeignService {
    @GetMapping("/payment/get/{id}")
    public CommonResult get(@PathVariable("id") Long id);
}

fallback类

@Component
public class PaymentFallbackService implements PaymentFeignService{
    @Override
    public CommonResult get(Long id) {
        return new CommonResult(444,"fallback...........",80);
    }
}

服务熔断配置

application或者注解方式配置

# 配置熔断策略:
hystrix:
  command:
    default:
      circuitBreaker:
        # 原理分析中解释配置含义
        # 强制打开熔断器 默认false关闭的。测试配置是否生效
#        forceOpen: false
        # 触发熔断错误比例阈值,默认值50%
        errorThresholdPercentage: 50
        # 熔断后休眠时长,默认值5秒
        sleepWindowInMilliseconds: 10000
        # 熔断触发最小请求次数,默认值是20
        requestVolumeThreshold: 10
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            # 熔断超时设置,默认为1秒
            timeoutInMilliseconds: 6000
//    @HystrixCommand(fallbackMethod = "fallbackFun",commandProperties = {
//            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器
//            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数
//            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
//            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),// 失败率达到多少后跳闸
//    })
    @HystrixCommand
    @GetMapping("/test/{id}")
    public String test(@PathVariable("id")Integer id){
        log.info("test......................");
        if(id<0){
            throw new RuntimeException("e..........");
        }
        return "test.............";
    }

测试:

  • 正常情况下访问test/1返回fallback,test/1可以正常返回
  • 当访问test/-1达到阈值后,熔断器开启。
  • 此时访问test/1也访问到fallback。
  • 继续访问几次test/1后恢复正常。
  • 说明熔断器的状态由开启到半开启到关闭。

Hystrix DashBoard

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值