SpringCloud——Hystrix断路器

一、概述

是一个用于处理分布式系统的延迟和容错的开源库。

断路器:是一种开关装置。当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出无法处理的异常,这样就保证了调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

(1)服务降级(fallback)

当服务器忙时,不让客户端处于一直等待状态,并立刻返回一个友好提示。
在这里插入图片描述

(2)服务熔断(break)

服务不可用时,停止对该服务的调用,过一段时间,直到完全恢复服务提供。
在这里插入图片描述

(3)服务限流(flowlimit)

严禁一窝蜂的过来拥挤,大家排队,一秒钟只允许通过 N 个,有序进行。

二、服务降级

  1. 引入pom
    <!-- hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-hystrix</artifactId>
        </dependency>

(1)在服务端启动策略

  1. 在启动类添加@EnableCircuitBreaker注解
  2. 设置服务降级策略(出错或者大于4秒时进入服务降级策略)
@Service
public class PaymentService {

    /**
     * 成功
     * @param id
     * @return
     */
    public String paymentInfo_OK(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + "   paymentInfo_OK,id:  " + id + "\t" + "好好好";
    }

    /**
     * timeout超时
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
            //4秒钟以内就执行正常的业务逻辑,反之执行降级方法
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000")  
    })
    public String paymentInfo_TimeOut(Integer id) { ;
        try {
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + "   paymentInfo_TimeOut,id:  " + id + "\t" + "等等等";
    }

    /**
     * 兜底
     */
    public String paymentInfo_TimeOutHandler(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + "出现错误,请稍后重试" + id + "\t";

    }
}

(2)在客户端启用策略

  1. 主启动类添加@EnableHystrix注解

  2. 修改配置文件

    server:
      port: 80
    
    spring:
      application:
        name: cloud-provider-hystrix-order
    
    eureka:
      client:
        register-with-eureka: true    #示表不向注册中心注册自己
        fetch-registry: true   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/
    
    ####################以下配置需要新增(ribbon相关配置和Feign超时相关)##################
    #全局配置
    # 请求连接的超时时间 默认的时间为 1 秒
    ribbon:
      ConnectTimeout: 5000
      # 请求处理的超时时间
      ReadTimeout: 5000
    
    # feign 配置
    feign:
      hystrix:
        enabled: true
    
    # hystrix 配置
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 60000
    
  3. controller

    @RestController
    public class OrderHystrixController {
    
        @Autowired
        private PaymentHystrixService paymentHystrixService;
    
        @GetMapping("/consumer/payment/hystrix/ok/{id}")
        public String paymentInfo_OK(@PathVariable("id") Integer id) {
            return paymentHystrixService.paymentInfo_OK(id);
        }
    
        // 添加服务降级相关配置
        @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod", commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")  //1钟以内就是正常的业务逻辑
        })
        @GetMapping("/consumer/payment/hystrix/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
            return paymentHystrixService.paymentInfo_TimeOut(id);
        }
    
        //服务降级方法
        public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
            return "我是消费者80";
        }
    
    }
    

(3)全局fallback

  • 添加@DefaultProperties注解

  • 添加@HystrixCommand注解

    @RestController
    @DefaultProperties(defaultFallback = "paymentTimeOutFallbackMethod")
    public class OrderHystrixController {
    
        @Autowired
        private PaymentHystrixService paymentHystrixService;
    
        @GetMapping("/consumer/payment/hystrix/ok/{id}")
        public String paymentInfo_OK(@PathVariable("id") Integer id) {
            return paymentHystrixService.paymentInfo_OK(id);
        }
    
        // 添加服务降级相关配置
        @HystrixCommand
        @GetMapping("/consumer/payment/hystrix/timeout/{id}")
        public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
            return paymentHystrixService.paymentInfo_TimeOut(id);
        }
    
        //全局服务降级方法(不能有参数)
        public String paymentTimeOutFallbackMethod() {
            return "我是,全局服务降级方法";
        }
    
    }
    

(4)使用fallbackFactory(常用)

服务降级三种实现之一

三、服务熔断

当出现错误或超时时,会首先启动服务降级,当次数达到一定的阈值时,会启动熔断机制(所有请求都不会转发),一段时间后,进入半开状态,让一个请求进行转发,若成功则关闭服务熔断
在这里插入图片描述

  1. service

    @Service
    public class PaymentService{
    
    	//服务熔断
        @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"), //失败率达到多少后跳闸,此处为60%(上面配置意思是:10秒钟内,10次请求,失败率60%就不让用了)
                // 具体需要配置哪些参数,在 HystrixCommandProperties.java 类中
        })
        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 不能负数,请稍候再试,(┬_┬)/~~     id: " +id;
        }
    }
    
    
  2. controller

    //===服务熔断
        @GetMapping("/payment/circuit/{id}")
        public String paymentCircuitBreaker(@PathVariable("id") Integer id){
            String result = paymentService.paymentCircuitBreaker(id);
            log.info("*******result:"+result);
            return result;
        }
    
  3. 常用配置

    @HystrixCommand(fallbackMethod = "str_fallbackMethod",
        groupKey = "strGroupCommand",
        commandKey = "strCommand",
        threadPoolKey = "strThreadPool",
    
        commandProperties = {
            //设置执行隔离策略,THREAD 表示线程池   SEMAPHORE:信号量隔离    默认为THREAD线程池
            @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
            // 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)
            @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
            // 配置命令执行的超时时间
            @HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),
            // 是否启用超时时间
            @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
            // 执行超时的时候是否中断
            @HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
            // 执行被取消的时候是否中断
            @HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),
            // 允许回调方法执行的最大并发数
            @HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
            // 服务降级是否启用,是否执行回调函数
            @HystrixProperty(name = "fallback.enabled", value = "true"),
            // 设置断路器是否起作用。
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
            // 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,
            // 如果滚动时间窗(默认10s)内仅收到了19个请求,及时这19个请求都失败了,断路也不会打开。
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
            // 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过 circuitBreaker.requestVolumeThreshold 的情况下,
            // 如果错误请求数的百分比超过 50,就把断路器设置为"打开"状态,否则就设置为"关闭"状态
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
            // 该属性用来设置当断路器打开之后的休眠时间窗。休眠时间窗结束之后,会将断路器置为"半开"状态,
            // 尝试熔断的请求命令,如果依然失败就将断路器继续设置为"打开"状态,如果成功就设置为"关闭"状态
            @HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),
            // 断路器强制打开
            @HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
            // 断路器强制关闭
            @HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
            // 滚动时间窗设置,该时间用于断路器判断健康度时,需要收集信息的持续时间
            @HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),
            // 该属性用来设置滚动时间窗统计指标信息时,划分"桶"的数量,断路器在手机指标信息的时候会根据设置的时间窗长度拆分成多个"桶"来累计各度量值,每个
            // "桶"记录了一段时间内的采集指标。比如 10 秒内拆分成 10 个"桶'收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常
            @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
            // 该属性用来设置对命令执行的延迟是否采用百分位数来跟踪和计算。如果设置为 false,name所有的概要统计都将返回-1
            @HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),
            // 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒
            @HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
            // 该属性用来设置百分位统计滚动窗口中使用 "桶" 的数量
            @HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),
            // 该属性用来设置在执行过程中每个"桶"中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数
            // 就从最初的位置开始重写。例如,将该值设置为100,滚动窗口为10秒,若在10秒内一个"桶"中发生了500次执行,
            // 那么该"桶"中只保留最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间
            @HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
            // 该属性用来设置采集意向断路器状态的健康快照(请求的成功、错误百分比)的间隔等待时间
            @HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),
            // 是否开启请求缓存
            @HystrixProperty(name = "requestCache.enabled", value = "true"),
            // HystrixCommand 的执行和事件是否打印日志到 HystrixRequestLog 中
            @HystrixProperty(name = "requestLog.enabled", value = "true")
        },
        threadPoolProperties = {
            // 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量
            @HystrixProperty(name = "coreSize", value = "10"),
            // 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,否则将使用 LinkedBlockingQueue 实现的队列
            @HystrixProperty(name = "maxQueueSize", value = "-1"),
            // 该参数用来为队列设置拒绝阈值。通过该参数,即使队列没有达到最大值也能拒绝请求。该参数主要是对 LinkedBlockingQueue 队列的补充,因为LinkedBlockingQueue
            // 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "5")
        }
    )
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值