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

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

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

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第1张图片
进而引起的服务雪崩:

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第2张图片
所以我们引入了Hystrix熔断器的概念。


文章目录

    • 一。Hystrix概念
      • 1.什么是Hystrix?
      • 2.Hystrix能干什么?
    • 二。Hystrix服务降级的基本配置
      • 1.导入依赖
      • 2.添加配置
    • 三。服务提供端接口代码示例
    • 四。Hystrix服务降级的几种实现方法
      • 1.@HystrixCommand实现
      • 2.@HystrixCommand+@DefaultProperties实现
      • 3.@FeignClient实现


一。Hystrix概念

1.什么是Hystrix?

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

2.Hystrix能干什么?

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

再来一个图解:

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

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

1.导入依赖

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


        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
        dependency>

2.添加配置

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

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

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

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

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

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. SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第6张图片
  2. 在启动类上加上@EnableCircuitBreaker注解,启用激活hystrix:SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第7张图片

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

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第8张图片
这就说明timeOut接口超时发生,走了指定的服务降级方法,这是因为在服务提供端该方法需要运行三秒钟以上,而在消费端做了配置只能等两秒,指定的时间内得不到返回的结果就会实行降级处理。

让我们将配置条件注释掉,再打开刚刚注释的模拟错误:
SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第9张图片
再次运行,结果一致:

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第10张图片
如果不采用服务降级处理,则程序会直接出现报错,无法运行,很容易造成服务雪崩:

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第11张图片
SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第12张图片

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 "这是   全局指定   服务出错/超时发生的降级处理方法";
    }

}

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

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第13张图片
指定调用降级方法接口:

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第14张图片
重新启动,访问http://localhost:8777/consumer/getInfo,发现该接口是调用的全局默认的降级方法:

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

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

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

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";
    }
}

注意说明:

SpringCloud微服务中Hystrix熔断器的使用(一)——服务降级(三种不同方式实现)_第17张图片
重新启动,访问http://localhost:8777/consumer/timeOut,页面如下所示:

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

你可能感兴趣的:(#,SpringCloud,SpringCloud,Hystrix)