SpringCloud之Hystrix

一、概述

在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。
Hystrix 负责监控服务之间的调用情况,连续多次失败的情况进行熔断保护。保护的方法就是使用 Fallback,当调用的服务出现故障时,就可以使用 Fallback 方法的返回值;Hystrix 间隔时间会再次检查故障的服务,如果故障服务恢复,将继续使用服务。

二、应用场景

2.1 服务降级

当发生以下情况,使整体负荷超出整体负载承受能力时,保证重要或基本服务正常运行,非重要服务延迟使用或暂停使用。

  • 程序运行异常
  • 超时
  • 服务熔断触发服务降级
  • 线程池/信号量打满

2.2 服务熔断

当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用

2.3 服务限流

在高并发系统的,网络的负载请求是有度的,可以通过对请求的并发数据进行限制来达到限流的操作。

三、配置

3.1 引入依赖

笔者尝试过不设置版本会导致依赖失败~,原因未明

<!--Hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

3.2 配置文件

#开启feign.hystrix服务降级功能
feign:
  hystrix :
    enabled : true

3.3 启动类

启动类上加入以下注解

@EnableHystrix

四、服务降级

4.1 controller层降级

消费者端和服务提供端所有代码添加降级方法,无论哪里出现错误,都会进入降级方法

4.1.1 全局降级方法

在cotroller加入注解

@DefaultProperties(defaultFallback = "goodsGlobalFallbackMethod")

对需要走降级的方法加入注解

@HystrixCommand

@DefaultProperties注解为全局降级方法,对于添加**@HystrixCommand注解的方法**会走全局公共降级方法,defaultFallback属性为降级方法名称

4.1.2 指定方法降级

对需要走降级的方法加入注解

@HystrixCommand(fallbackMethod = "goodsTimeOutFallbackMethod",
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
    })

fallbackMethod指定降级方法的方法名
commandProperties设置降级条件,以上面为例,当请求超过2000毫米时,触发降级

4.2 解耦式降级

利用feign设置fallback降级方法,只有服务端出现异常才会进入降级方法,消费端的异常会将错误抛出,并不会进入降级方法
这种方式需要额外引入依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>

配置文件中新增

feign:
  hystrix:
    enabled: true
  circuitbreaker:
    enabled: true

Feigin添加fallback

@Service
@FeignClient(value = "GOODS-PROVIDER",fallback = GoodsFallbackService.class)
public interface GoodsService {

    @RequestMapping("/goods/findAll")
    List<GoodsBean> findAll();

    @RequestMapping("/goods/buy")
    GoodsBean buy(@RequestParam(value = "id") Long id, @RequestParam(value = "num") Long num);

    @RequestMapping("/goods/findById")
    GoodsBean findById(@RequestParam Long id);

    @RequestMapping("/goods/paymentInfo_OK")
    String paymentInfo_OK(@RequestParam Long id);

    @RequestMapping("/goods/paymentInfo_TimeOut")
    String paymentInfo_TimeOut(@RequestParam Long id);
}

此类实现本接口,每个实现方法即为调用服务的降级方法

@Component
public class GoodsFallbackService implements GoodsService {
    @Override
    public List<GoodsBean> findAll() {
        return new ArrayList<>();
    }

    @Override
    public GoodsBean buy(Long id, Long num) {
        return null;
    }

    @Override
    public GoodsBean findById(Long id) {
        return null;
    }

    @Override
    public String paymentInfo_OK(Long id) {
        return "paymentInfo_OK的降级方法";
    }

    @Override
    public String paymentInfo_TimeOut(Long id) {
        return "paymentInfo_TimeOut的降级方法";
    }
}

五、服务熔断

上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用

5.1 设置熔断属性

  • circuitBreaker.enabled:是否启用熔断器,默认true
  • circuitBreaker.forceOpen:强制打开熔断器,默认false。
  • circuitBreaker.forceClosed:强制关闭熔断器,默认false。
  • circuitBreaker.errorThresholdPercentage:错误率,默认50%。在一段时间内,服务调用超时或者失败率超过50%,则打开熔断器
  • circuitBreaker.requestVolumeThreshold:默认20。意思为在一段时间内要有20个及以上的请求才会去计算错误率。比如只来了19个请求,就算全失败了,那也不算错误率100%
  • circuitBreaker.sleepWindowInMilliseconds:半开状态试探睡眠时间,默认为5000ms。也就是熔断器打开5s后,开始半打开状态,放出一点请求去调用服务,试探一下能否成功

以之前做的秒杀方法为例

@Transactional
@CacheEvict(cacheNames = "goods",key = "'goods'+#id")
@HystrixCommand(fallbackMethod = "seckillCircuitBreaker_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 buy(Long id,Long num){
    GoodsBean goodsBean = goodsMapper.selectById(id);
    if(goodsBean.getNum()<num){
        throw new RuntimeException("库存不足");
    }
    goodsBean.setNum(goodsBean.getNum()-num);
    goodsMapper.updateById(goodsBean);
    return id.toString();
}

/**
* 秒杀熔断方法
* */
public String seckillCircuitBreaker_fallback(Long id,Long num){
    return "秒杀产品失败";
}

5.2 测试

发起错误的参数,一直走服务降级方法,直到服务熔断打开,传入正确的参数请求
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值