Hystrix

Hystrix熔断器

为什么要使用Hystrix?

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC)。为了保证其高可用,单个服务器又必须集群部署,由于网络或者自身的原因,并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务雪崩,为了解决这个问题,就出现了断路器模型。

Hystrix是一个帮助解决分布式系统交互时超时处理和容错的类库,它同样拥有保护系统的能力

hystrix的出现就是为了解决在分布式系统架构中的 级联故障(雪崩)

什么时雪崩效应?

分布式系统中,经常会出现某个基础服务不可用造成整个系统不可用的情况,这种现象被称为服务雪崩效应.

一个服务失败,导致整条链路的服务都失败的情形

原因:

  1. 某几个机器故障:例如机器的硬驱动引起的错误,或者一些特定的机器上出现一些的bug(如,内存中断或者死锁)。
  2. 服务器负载发生变化:某些时候服务会因为用户行为造成请求无法及时处理从而导致雪崩,例如阿里的双十一活动,若没有提前增加机器预估流量则会造服务器压力会骤然增大从而挂掉。
  3. 人为因素:比如代码中的路径在某个时候出现bug
Hystix主要功能
  1. 隔离 (加速系统响应时间 从而不至于线程阻塞)

    1. 线程池隔离

      1. 为每个服务分配各自的线程池

    2. 信号量隔离

      1. 访问次数限制,只允许一定数量的访问
  2. 降级:异常、超时

  3. 熔断

  4. 限流


组件三步走
  1. pom spring-cloud-starter-netflix-hystrix

  2. yml

    1. 服务提供方设置Hystrix的超时时间

      hystrix:
        command:
          default:
            execution:
              isolation:
                thread:
                  timeoutInMilliseconds: 3000
      
    2. 消费方(feign)开启降级功能

      # 开启feign对hystrix的支持
      feign:
        hystrix:
          enabled: true
      
  3. Enable注解

    1. @EnableCircuitBreaker (开启熔断器)

    2. 三合一注解 @SpringCloudApplication

    3. @SpringBootApplication

    4. @EnableDiscoveryClient

      @EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心。

    5. @EnableCircuitBreaker


单独使用Hystrix(提供方降级)

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;

    /**
     * 降级:
     *  1. 出现异常
     *  2. 服务调用超时
     *      * 默认1s超时
     *
     *  @HystrixCommand(fallbackMethod = "findOne_fallback")
     *      fallbackMethod:指定降级后调用的方法名称
     */
    /*
    public @interface HystrixCommand {
         String fallbackMethod() default "";
         HystrixProperty[] commandProperties() default {};
          注解类型的一维数组
    }
        从HystrixCommandProperties类中
        private final HystrixProperty<Integer> executionTimeoutInMilliseconds;
        this.executionTimeoutInMilliseconds = getProperty(propertyPrefix, key, 
                        "execution.isolation.thread.timeoutInMilliseconds", 
                        builder.getExecutionIsolationThreadTimeoutInMilliseconds(),
                         default_executionTimeoutInMilliseconds);
     */

    @GetMapping("/findOne/{id}")
    @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
            //设置Hystrix的超时时间,默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") //可以使用配置文件代替
    })
    public Goods findOne(@PathVariable("id") int id){

        //1.造个异常
        int i = 3/0;
        try {
            //2. 休眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
        return goods;
    }


    /**
     * 定义降级方法:
     *  1. 方法的返回值需要和原方法一样
     *  2. 方法的参数需要和原方法一样
     */
    public Goods findOne_fallback(int id){
        Goods goods = new Goods();
        goods.setTitle("降级了~~~");

        return goods;
    }

}

Feign集成(消费方降级)

feign组件已经集成了Hystrix组件

  1. 定义类 实现 Feign 客户端接口
/**
 * Feign 客户端的降级处理类
 * 1. 定义类 实现 Feign 客户端接口
 * 2. 使用@Component注解将该类的Bean加入SpringIOC容器
 */
@Component
public class GoodsFeignClientFallback implements GoodsFeignClient {
    @Override
    public Goods findGoodsById(int id) {
        Goods goods = new Goods();
        goods.setTitle("又被降级了~~~");
        return goods;
    }
}
  1. 在 @FeignClient 注解中使用 fallback 属性设置降级处理类.

    @FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
    public interface GoodsFeignClient {
        @GetMapping("/goods/findOne/{id}")
        public Goods findGoodsById(@PathVariable("id") int id);
    }
    

注意:

  1. 当服务提供方休眠两秒,而超时时间设置为3秒,没有触发提供方降级,而调用方超时时间默认为1秒,会触发调用方降级方法
  2. 当服务提供方出现异常时,会触发提供方降级方法

熔断

  • Hystrix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(最小请求数不低于20次/10s 失败率大于等于50%),会打开断路器,拒绝所有请求,直到服务恢复正常为止。

  • 断路器的三种状态:打开、半开、关闭

  • 正常情况下,访问时,如果失败返回降级方法

  • 如果请求数不低于20次/10s 失败率大于等于50%,会打开熔断器,此时会拒绝所有请求(无论好的坏的,统一返回降级方法)

  • 断路器开启时间到了(默认5s)就到了半开状态

  • 半开状态下,会放进来一个请求,如果成功就close,否则继续open

posted @ 2020-10-19 15:57  风冰水  阅读(144)  评论(0编辑  收藏  举报