SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)

前言:分布式系统面临的问题

复杂分布式体系结构中的应用程序 有数10个依赖关系,每个依赖关系在某些时候将不可避免地失败,如下图所示:

在这里插入图片描述
进而引起的服务雪崩:

在这里插入图片描述
所以我们引入了Hystrix熔断器的概念。



一。Hystrix概念

1.什么是Hystrix?

在这里插入图片描述

2.Hystrix能干什么?

  1. 服务降级:当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
  2. 服务熔断:如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
  3. 服务限流:限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。

再来一个图解:

在这里插入图片描述

二。Hystrix服务降级的基本配置

1.导入依赖

在pom.xml文件中导入以下依赖:

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

2.添加配置

在application.yml文件中添加以下配置:

#开启hystrix熔断器
feign:
  hystrix:
    enabled: true

注意添加位置:(顶格书写)

在这里插入图片描述

三。服务提供端接口代码示例

8001服务提供端控制器代码:

@RestController
@RequestMapping("provider")
public class ProviderController {

    @GetMapping("getInfo")
    public String getInfo(){
        return "这是8001端口在提供服务";
    }

    /**
     * 模拟超时过程
     * @return
     */
    @GetMapping("timeOut")
    public String timeOut() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        return "这是8001端口在模拟超时过程";
    }

}

四。Hystrix服务降级的几种实现方法

1.@HystrixCommand实现

这里主要说明的是利用@HystrixCommand注解给特定接口实现服务降级。实现过程如下:

编写ConsumerClient类调用服务提供端:

@FeignClient(value = "service-provider")
public interface ConsumerClient {
  
    // 测试调用
    @GetMapping("/provider/getInfo")
    public String getInfo();

    /**
     * 调用模拟超时接口
     * @return
     */
    @GetMapping("/provider/timeOut")
    public String timeOut();
    
}

控制器代码如下:

@RequestMapping("consumer")
@RestController
public class ConsumerController {

    @Autowired
    private ConsumerClient consumerClient;

    /**
     * 正常方法调用
     * @return
     */
    @RequestMapping("getInfo")
    public String getInfoByTemplate(){
        return consumerClient.getInfo();
    }

    /**
     * 模拟超时调用
     * @return
     */
    @RequestMapping("timeOut")
    //配置熔断器,fallbackMethod为降级调用方法,commandProperties为触发服务降级配置
    @HystrixCommand(fallbackMethod = "Error",commandProperties = {
            //条件设置为2s后未返回结果则发生降级
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    })
    public String timeOut(){
        //模拟程序出错
        //int a=10/0;
        return consumerClient.timeOut();
    }

    /**
     * timeOut降级处理方法
     * @return
     */
    public String Error(){
        return "这是   timeOut接口   服务出错/超时发生的降级处理方法";
    }

需要注意的是:

  1. 在这里插入图片描述
  2. 在启动类上加上@EnableCircuitBreaker注解,启用激活hystrix:在这里插入图片描述

依次启动,这里做一个补充说明,消费端端口为8777,服务提供端端口为8001,访问http://localhost:8777/consumer/timeOut,出现以下内容:

在这里插入图片描述
这就说明timeOut接口超时发生,走了指定的服务降级方法,这是因为在服务提供端该方法需要运行三秒钟以上,而在消费端做了配置只能等两秒,指定的时间内得不到返回的结果就会实行降级处理。

让我们将配置条件注释掉,再打开刚刚注释的模拟错误:
在这里插入图片描述
再次运行,结果一致:

在这里插入图片描述
如果不采用服务降级处理,则程序会直接出现报错,无法运行,很容易造成服务雪崩:

在这里插入图片描述
在这里插入图片描述

2.@HystrixCommand+@DefaultProperties实现

这里是使用@HystrixCommand+@DefaultProperties注解实现服务降级处理,@DefaultProperties是给该类中全部要做降级处理的接口方法统一制定一个降级调用方法,但是如果接口另外做了特殊指定,则调用该接口指定的降级调用方法。实现过程如下:

控制器代码如下:

@RequestMapping("consumer")
@RestController
@DefaultProperties(defaultFallback = "GlobalError")
public class ConsumerController {

    @Autowired
    private ConsumerClient consumerClient;

    @RequestMapping("getInfo")
    @HystrixCommand
    public String getInfoByTemplate(){
        //模拟程序出错
        int a=10/0;
        return consumerClient.getInfo();
    }

    /**
     * 模拟超时调用
     * @return
     */
    @RequestMapping("timeOut")
    //配置熔断器,fallbackMethod为降级调用方法,commandProperties为触发服务降级配置
    @HystrixCommand(fallbackMethod = "Error",commandProperties = {
            //条件设置为2s后未返回结果则发生降级
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    })
    public String timeOut(){
        //模拟程序出错
        //int a=10/0;
        return consumerClient.timeOut();
    }

    /**
     * timeOut降级处理方法
     * @return
     */
    public String Error(){
        return "这是   timeOut接口   服务出错/超时发生的降级处理方法";
    }


    public String GlobalError(){
        return "这是   全局指定   服务出错/超时发生的降级处理方法";
    }

}

指定全局降级方法:
在这里插入图片描述
未特殊指定降级方法接口:

在这里插入图片描述
指定调用降级方法接口:

在这里插入图片描述
重新启动,访问http://localhost:8777/consumer/getInfo,发现该接口是调用的全局默认的降级方法:

在这里插入图片描述

访问http://localhost:8777/consumer/timeOut,发现该接口调用的还是指定的降级方法:

在这里插入图片描述

3.@FeignClient实现

相信很多的小伙伴看完以上两种实现方法,发现了一个问题。我们平时在控制器里面应该就是注重业务逻辑的编写,你再引入一些全局或者指定的降级方法,这样控制器代码不就乱套了吗?代码耦合度不就高了吗?我们平时追求的就是降低代码的耦合度,尽量使得代码看起来优雅美观,还能有优美的实现方法吗?那么它就来了!这里是用@FeignClient注解来实现的,它是由一个实现了服务调用接口的类,然后在该类相应的实现中编写了降级方法。具体实现过程如下:

服务调用类:

@FeignClient(value = "service-provider",fallback = ConsumerFallback.class)
public interface ConsumerClient {
  
    // 测试调用
    @GetMapping("/provider/getInfo")
    public String getInfo();

    /**
     * 调用模拟超时接口
     * @return
     */
    @GetMapping("/provider/timeOut")
    public String timeOut();

}

服务调用接口实现类:

@Component
public class ConsumerFallback implements ConsumerClient {
    @Override
    public String getInfo() {
        return "这是  @FeignClient注解  返回的服务降级办法,getInfo";
    }

    @Override
    public String timeOut() {
        return "这是  @FeignClient注解  返回的服务降级办法,timeOut";
    }
}

注意说明:

在这里插入图片描述
重新启动,访问http://localhost:8777/consumer/timeOut,页面如下所示:

在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Keson Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值