SpringCloud(22)之Sentinel实战应用

一、Sentinel核心库

sentinel主页:主页 · alibaba/Sentinel Wiki · GitHub

1.1 Sentinel介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

1)Sentinel核心组件

1:核心库(Java 客户端) :不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同 时对 Dubbo / Spring Cloud 等框架也有较好的支持。

2:控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。

2)Sentinel VS Hystrix

|--------------|------------------------------------|-----------------------------|
| 对比内容 | Sentinel | Hystrix |
| 隔离策略 | 信号量隔离 | 线程池隔离/信号量隔离 |
| 熔断降级策略 | 基于响应时间或失败比率 | 基于失败比率 |
| 实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) |
| 规则配置 | 支持多种数据源 | 支持多种数据源 |
| 扩展性 | 多个扩展点 | 插件的形式 |
| 基于注解的支 持 | 支持 | 支持 |
| 限流 | 基于 QPS,支持基于调用关系的限流 | 不支持 |
| 流量整形 | 支持慢启动、匀速器模式 | 不支持 |
| 系统负载保护 | 支持 | 不支持 |
| 控制台 | 开箱即用,可配置规则、查看秒级监控、机器 发现等 | 不完善 |
| 常见框架的适 配 | Servlet、Spring Cloud、 Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |

3)Sentinel概念

  • 资源:资源是Sentinel的关键概念,他可以是Java应用程序的任何内容,例如,由应用程序提供的服务,或由应用程序调用其他服务提供的服务,甚至可以是一段代码; 只要通过Sentinel API定义的代码,就是资源,能够被Sentinel保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源来标示资源。
  • 规则:围绕资源的实时状态设定的规则,可以包括流量控制规则,熔断规则以及系统保护规则,所有规则可以动态实时调整。

1.2 Sentinel核心功能

1.2.1 流量控制

流量控制在网络传输中是一个常用的概念,他用于调整网络包的发送数据,然而,从系统的稳定性角度考虑,也有非常多的讲究。在任意时刻到来的请求往往是随机不可控的,而系统的处理能力有限,我们需要根据系统的的处理能力对流量进行控制.Sentinel作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:

流量控制设计理念

流量控制有以下几个角度:

  • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
  • 运行指标,例如:QPS、线程池、系统负载等;
  • 控制的效果,例如直接限流、冷启动、排队等;

Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

1.2.2 熔断降级

除了流量控制之外,及时对调用链路中的不稳定因素进行熔断也是Sentinel的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求堆积,进而导致级联故障。

Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。

1)Sentinel熔断设计理念

Hystrix通过线程池隔离的方式,来对依赖进行了隔离,这样做的好处就是资源和资源之间 做到了最彻底的隔离。缺点就是增加了线程切换的成本,还要先给各个资源做线程池大小的分配。

Sentinel对这个问题采取了两种手段:

  • 通过并发线程数进行控制

和资源池隔离的方法不同,Sentinel通过限制资源并发线程的数量,来减少不稳定资源对其他资源的影响。也不需要预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间过长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源商堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才会开始继续处理请求。

  • 通过响应时间对资源进行降级

除了对并发线程数进行控制外,Sentinel还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会直接被拒绝,直到过了指定时间的窗口后才恢复。

2)系统自适应保护

Sentinel同时提供系统维度的自适应能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统奔溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其他机器上,如果这个时候其他的机器也处于一个边缘状态,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

针对这个情况,Sentinel提供了对应的保护机制,让系统的入口流量和系统负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

1.3 Sentinel熔断限流

Sentinel可以简单的分为Sentinel核心库和Dashboard。核心库不依赖Dashboard,但是结合Dashboard可以取得最后的效果。我们先来学习一下Sentinel核心库的使用。后面在学习Dashboard的使用。

在我们项目中,用户请求通过 hailtaxi-gateway路由到 hailtaxi-driver 或者 hailtaxi-order ,还 有可能在 hailtaxi-order 中使用feign调用 hailtaxi-driver ,所以我们有可能在单个服务中实现熔 断限流,也有可能要集成feign调用实现熔断限流,还有可能在微服务网关中实现熔断限流。我们接下 来一步一步实现每一种熔断限流操作。

1.3.1 Springboot集成

如果在Springboot项目中集成,首先需要引入依赖,并使用@SentinelResource标记资源。

1.3.1.1 @SentinelResource注解

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。

@SentinelResource 注解包含以下属性:

|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| value | 资源名称,必需项 (不能为空 ) |
| blockHandler / blockHandlerClass | blockHandler 对应处理 BlockException 的函数名称,可选项。 ♞ blockHandler 函数访问范围需要是 public ;♞ 返回类型需要与原 方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的 参数,类型为 BlockException。 ♞ blockHandler 函数默认需要和 原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必 需为 static 函数,否则无法解析。 |
| fallback / fallbackClass | fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。 fallback 函数签名和位置要求: ♞ 返回值类型必须与原函数返回值类型一 致; ♞ 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。 ♞ fallback 函数默认 需要和原方法在同一个类中。若希望使用其他类的函数,则可以指 定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需 为 static 函数,否则无法解析。 |
| defaultFallback(1.6.0 开 始) | 默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑 (即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类 型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处 理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。 defaultFallback 函数签名要求: ♞ 返回值类型必须与原 函数返回值类型一致; ♞ 方法参数列表需要为空,或者可以额外多 一个 Throwable 类型的参数用于接收对应的异常。 ♞ defaultFallback 函数默认需要和原方法在同一个类中。若希望使用 其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对 象,注意对应的函数必需为 static 函数,否则无法解析。 |
| exceptionsToIgnore(1.6.0 开始) | 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。 |
| entryType | entry 类型,可选项(默认为 EntryType.OUT) |

1.3.1.2 blockHandler

在对应的模块中加入依赖:

XML 复制代码
        <!--sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

我们为 info()方法添加一个 @SentinelResource注解,用来标注资源,表示当前方法需要执行限流、降级,在注解中添加value属性,用来标注资源,说白了就是给当前资源起个名字,blockHandler 用来表示当前方法发生 BlockException 异常的时候,将处理流程交给指定的方法 blockExHandler() 处理,此时 blockExHandler()方法必须和抛出异常的方法在同一个类中,这是一种降级操作,代码如 下:

java 复制代码
    @SentinelResource(value = "info",blockHandler = "blockExHandler")
    public Driver info(@PathVariable(value = "id")String id) throws InterruptedException{
        Driver driver = driverService.findById(id);
        //if(id.equals("1")){
        //    TimeUnit.SECONDS.sleep(10);
        //}
        if(driver==null){
            //throw new RuntimeException("司机不存在");
            throw new SystemBlockException("info","hailtaxi-driver");//必须抛出BlockException才会生效
        }
        driver.setName(driver.getName()+",IP="+ip);
        return driver;
    }

    /***
     * BlockException异常处理
     */
    public Driver blockExHandler(String id,BlockException ex){
        Driver driver = new Driver();
        driver.setId(id);
        driver.setName("bbb");
        return driver;
    }

如果访问一个没有的数据就会报错异常,此时就会走blockhandler里面的逻辑。

1.3.1.3 fallback使用

如果我们希望抛出任何异常都能处理,都能调用默认处理方法,而并非只是 BlockException异常才调 用,此时可以使用 @SentinelResource 的 fallback属性,代码如下:

java 复制代码
    @SentinelResource(value = "info",fallback ="exHandler")
    public Driver info(@PathVariable(value = "id")String id) throws InterruptedException{
        Driver driver = driverService.findById(id);
        //if(id.equals("1")){
        //    TimeUnit.SECONDS.sleep(10);
        //}
        if(driver==null){
            throw new RuntimeException("司机不存在");
//            throw new SystemBlockException("info","hailtaxi-driver");//必须抛出BlockException才会生效
        }
        driver.setName(driver.getName()+",IP="+ip);
        return driver;
    }

    /***
     * 异常处理
     */
    public Driver exHandler(String id){
        Driver driver = new Driver();
        driver.setId(id);
        driver.setName("aaa");
        return driver;
    }

访问 http://localhost:18081/driver/info/3 测试出错效果如下:

如果我们处理异常逻辑跟原方法不在同一个类中,可以使用@SentinelResource注解的fallbackclass实现,代码如下:

java 复制代码
@SentinelResource(value = "info",fallback ="exHandler" ,fallbackClass ="xx.xxx.xxx.xx.Xxx")
1.3.1.4 defaultFallback

上面无论是 blockHandler还是 fallback ,每个方法发生异常,都要为方法独立创建一个处理异常的 方法,效率非常低,我们可以使用 @SentinelResource注解的 defaultFallback属性,为一个类指定 一个全局的处理错误的方法,代码如下:

java 复制代码
@RestController
@RequestMapping(value = "/driver")
@RefreshScope
@SentinelResource(defaultFallback ="defaultExFallback")
public class DriverController {

    /***
     * 异常处理
     */
    public Driver defaultExFallback() {
        Driver driver = new Driver();
        driver.setName("系统繁忙,请稍后再试!");
        return driver;
    }
}

此时需要注意, defaultFallback属性指定的方法入参必须为空,最多可以增加一个异常对象。我们访问 http://localhost:18081/driver/info/3 效果如下:

1.3.2 限流规则

Sentinel支持多种限流规则,规则我们可以在代码中直接定义,规则属性如下:

|-----------------|---------------------------------------|---------------------|
| Field | 说明 | 默认值 |
| resource | 资源名,资源名是限流规则的作用对象 | |
| count | 限流阈值 | |
| grade | 限流阈值类型,QPS 模式(1)或并发线程数模式 ( 0 ) | QPS 模式 |
| limitApp | 流控针对的调用来源 | default ,代表不区 分调用来源 |
| strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直 接) |
| controlBehavior | 流控效果(直接拒绝/WarmUp/匀速+排队等 待),不支持按调用关系限流 | 直接拒绝 |
| clusterMode | 是否集群限流 | 否 |

1.3.2.1 流量控制

理解上面规则的定义之后,我们可以通过调用 FlowRuleManager.loadRules() 方法来用硬编码的方 式定义流量控制规则。

1)QPS流量控制

我们先实现流量基于QPS控制,在 hailtaxi-driver 的 DriverApplication启动类上添加如下方法加 载限流规则,当 DriverApplication初始化完成之后加载规则,代码如下:

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.xxxxx.driver.mapper")
@EnableAutoDataSourceProxy
public class DriverApplication {

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext applicationContext = SpringApplication.run(DriverApplication.class,args);
    }

    /***
     * 初始化规则
     */
    @PostConstruct
    private void initFlowQpsRule() {
        //规则集合
        List<FlowRule> rules = new ArrayList<FlowRule>();
        //定义一个规则
        FlowRule rule = new FlowRule("info");
        // 设置阈值
        rule.setCount(2);
        //设置限流阈值类型
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS控制
//        rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);//线程数控制
        //default,代表不区分调用来源
        rule.setLimitApp("default");
        //将定义的规则添加到集合中
        rules.add(rule);
        //加载规则
        FlowRuleManager.loadRules(rules);
    }
}

我们访问 http://localhost:18081/driver/info/1此时不会抛出异常,但是频繁刷新,则会调用降 级方法,效果如下:

2)线程数流量控制

我们修改限流阈值类型,代码如下:

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.xxxxx.driver.mapper")
@EnableAutoDataSourceProxy
public class DriverApplication {

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext applicationContext = SpringApplication.run(DriverApplication.class,args);
    }

    /***
     * 初始化规则
     */
    @PostConstruct
    private void initFlowQpsRule() {
        //规则集合
        List<FlowRule> rules = new ArrayList<FlowRule>();
        //定义一个规则
        FlowRule rule = new FlowRule("info");
        // 设置阈值
        rule.setCount(2);
        //设置限流阈值类型
        rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);//线程数控制
        //default,代表不区分调用来源
        rule.setLimitApp("default");
        //将定义的规则添加到集合中
        rules.add(rule);
        //加载规则
        FlowRuleManager.loadRules(rules);
    }
}

此时再来访问 http://localhost:18081/driver/info/1我们发现用浏览器无论怎么访问都不会出现 降级现象,但是如果用Jmeter模拟多个线程,效果就不一样了,效果如下:

1.3.2.2 熔断降级

熔断降级规则包含下面几个重要的属性:

|--------------------|-------------------------------------------------|---------|
| Field | 说明 | 默认 值 |
| resource | 资源名,即规则的作用对象 | |
| grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调 用比 例 |
| count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调 用);异常比例/异常数模式下为对应的阈值 | |
| timeWindow | 熔断时长,单位为 s | |
| minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出 阈值也不会熔断(1.7.0 引入) | 5 |
| statIntervalMs | 统计时长(单位为 ms ),如 60*1000 代表分钟级(1.8.0 引 入) | 1000 ms |
| slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) | |

同一个资源可以同时有多个降级规则。理解上面规则的定义之后,我们可以通过调用 DegradeRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则,在 DriverApplication 规则定义如下:

java 复制代码
    /***
     * 熔断降级规则
     */
    @PostConstruct
    private void initDegradeRule() {
        //降级规则集合
        List<DegradeRule> rules = new ArrayList<DegradeRule>();
        //降级规则对象
        DegradeRule rule = new DegradeRule();
        //设置资源
        rule.setResource("info");
        //设置触发降级阈值
        rule.setCount(2);
        /**
         * 熔断降级策略,支持慢调用比例/异常比例/异常数策略
         * DEGRADE_GRADE_RT:平均响应时间
         * DEGRADE_GRADE_EXCEPTION_RATIO:异常比例数量
         * DEGRADE_GRADE_EXCEPTION_COUNT:异常数
         */
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        //熔断窗口时长,单位为 s
        rule.setTimeWindow(10);
        //将规则添加到集合中
        rules.add(rule);
        //加载规则
        DegradeRuleManager.loadRules(rules);
    }
1.3.2.3 系统自我保护

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体 平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量 和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统规则包含下面几个重要的属性:

|-------------------|-------------------------|-------------|
| Field | 说明 | 默认值 |
| highestSystemLoad | load1 触发值,用于触发自适应控制阶段 | -1 (不生效) |
| avgRt | 所有入口流量的平均响应时间 | -1 (不生效) |
| maxThread | 入口流量的最大并发数 | -1 (不生效) |
| qps | 所有入口资源的 QPS | -1 (不生效) |
| highestCpuUsage | 当前系统的 CPU 使用率(0.0-1.0 ) | -1 (不生效) |

理解上面规则的定义之后,我们可以通过调用 SystemRuleManager.loadRules() 方法来用硬编码的 方式定义流量控制规则。

java 复制代码
    /***
     * 系统自我保护
     */
    //@PostConstruct
    private void initSystemRule() {
        //系统自我保护集合
        List<SystemRule> rules = new ArrayList<>();
        //创建系统自我保护规则
        SystemRule rule = new SystemRule();
        //CPU使用率 值为0-1,-1 (不生效)
        rule.setHighestCpuUsage(0.2);
        //所有入口资源的 QPS,-1 (不生效)
        rule.setQps(10);
        //入口流量的最大并发数,-1 (不生效)
        rule.setMaxThread(5);
        //所有入口流量的平均响应时间,单位:秒,-1 (不生效)
        rule.setAvgRt(5);
        //load1 触发值,用于触发自适应控制阶段,系统最高负载,建议取值 CPU cores * 2.5
        rule.setHighestSystemLoad(20);
        //将规则加入到集合
        rules.add(rule);
        SystemRuleManager.loadRules(rules);
    }
1.3.2.4 热点数据

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数 据,并对其访问进行限制。比如:

1:商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制

2:用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调 用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效.

Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点 参数限流支持集群模式。

要使用热点参数限流功能,需要引入以下依赖:

java 复制代码
        <!--热点参数-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-parameter-flow-control</artifactId>
            <version>1.8.1</version>
        </dependency>

然后为对应的资源配置热点参数限流规则,并在 entry 的时候传入相应的参数,即可使热点参数限流 生效。

热点参数规则( ParamFlowRule )类似于流量控制规则( FlowRule ):

|-------------------|----------------------------------------------------------------------------|-------------|
| 属性 | 说明 | 默认值 |
| resource | 资源名,必填 | |
| count | 限流阈值,必填 | |
| grade | 限流模式 | QPS 模 式 |
| durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s |
| controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开 始支持 | 快速失 败 |
| maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本 开始支持 | 0ms |
| paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 | |
| paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值, 不受前面 count 阈值的限制。 仅支持基本类型和字符串 类型 | |

我们可以对热门参数比如下标为0的参数流量进行控制,对热点数据执行特殊限流,比如参数值为 tj 的 时候执行限流,在 DriverApplication 中创建限流配置,代码如下:

java 复制代码
    /***
     * 热点参数初始化
     */
    @PostConstruct
    private static void initParamFlowRules() {
        ParamFlowRule rule = new ParamFlowRule("search")
                //参数下标为0
                .setParamIdx(0)
                //限流模式为QPS
                .setGrade(RuleConstant.FLOW_GRADE_QPS)
                //统计窗口时间长度(单位为秒)
                .setDurationInSec(10)

                /**
                 * 流控效果(支持快速失败和匀速排队模式)
                 * CONTROL_BEHAVIOR_DEFAULT:限流行为,直接拒绝
                 * CONTROL_BEHAVIOR_WARM_UP:限流行为,匀速排队 冷启动
                 * CONTROL_BEHAVIOR_RATE_LIMITER:限流行为,匀速排队
                 */
                .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)
                //最大排队等待时长(仅在匀速排队模式生效  CONTROL_BEHAVIOR_RATE_LIMITER)
                //.setMaxQueueingTimeMs(600)
                //最大阈值为5
                .setCount(5);

        // 为特定参数单独设置阈值.
        //如下配置:当下标为0的参数值为tj的时候,阈值到达2的时候则执行限流
        ParamFlowItem item = new ParamFlowItem()
                //参数类型为int类型
                .setClassType(String.class.getName())
                //设置阈值为2
                .setCount(2)
                //需要统计的值
                .setObject(String.valueOf("tj"));
        rule.setParamFlowItemList(Collections.singletonList(item));
        //加载热点数据
        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
    }

1.3 Sentinel对OpenFeign支持

Sentinel 适配了 Feign 组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依 赖外还需要 2 个步骤:

1:配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true

2:加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效

1)引入依赖

java 复制代码
        <!--sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.5.RELEASE</version>
        </dependency>

        <!--Openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2)还需要在Feign调用客户端中开启Feign的支持

XML 复制代码
feign:
  compression:
    request:
      enabled: true # 开启请求压缩
      mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
      min-request-size: 2048 # 设置触发压缩的大小下限
      #以上数据类型,压缩大小下限均为默认值
    response:
      enabled: true # 开启响应压缩
  #开启Sentinel对Feign的支持
  sentinel:
    enabled: true

1.3.1 fallback

我们可以为Feign接口创建一个实现类,在实现类中处理程序异常降级处理方法,代码如下:

java 复制代码
@Component
public class DriverFeignFallback implements DriverFeign {

    /**
     * status()降级处理方法
     */
    @Override
    public Driver status(String id, Integer status) {
        Driver driver = new Driver();
        driver.setId(id);
        driver.setStatus(status);
        driver.setName("系统比较繁忙,请您稍后再试!");
        return driver;
    }
}

我们还需要在Feign接口上添加 fallback属性指定讲解处理的类,代码如下:

java 复制代码
@FeignClient(value = "hailtaxi-driver",fallback = DriverFeignFallback.class)

1.3.2 fallbackFactory

我们可以为Feign接口创建一个降级处理的工厂对象,在工厂对象中处理程序异常降级处理方法,代码 如下:

java 复制代码
@Component
public class DriverFeignFallbackFactory implements FallbackFactory<DriverFeign> {

    @Override
    public DriverFeign create(Throwable throwable) {
        return new DriverFeign() {

            /**
             * status()降级处理方法
             */
            @Override
            public Driver status(String id, Integer status) {
                Driver driver = new Driver();
                driver.setId(id);
                driver.setStatus(status);
                driver.setName("系统比较繁忙,请您稍后再试!");
                return driver;
            }
        };
    }
}

我们还需要在Feign接口上添加 fallbackFactory属性指定讲解处理的类,代码如下:

java 复制代码
@FeignClient(value = "hailtaxi-driver",fallbackFactory =
DriverFeignFallbackFactory.class)

此时我们测试,效果如下:

相关推荐
Java探秘者5 小时前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea
杨荧10 小时前
【JAVA开源】基于Vue和SpringBoot的水果购物网站
java·开发语言·vue.js·spring boot·spring cloud·开源
半夜下雨14 小时前
SpringCloud学习记录|day2
spring cloud
杨荧19 小时前
【JAVA开源】基于Vue和SpringBoot的周边产品销售网站
java·开发语言·vue.js·spring boot·spring cloud·开源
kong79069281 天前
SpringCloud入门(十一)路由过滤器和路由断言工厂
spring cloud·gateway 网关路由
customer081 天前
【开源免费】基于SpringBoot+Vue.JS美容院管理系统(JAVA毕业设计)
android·java·vue.js·spring boot·spring cloud·开源
半夜下雨1 天前
SpringCloud学习记录|day1
spring cloud
Wang's Blog2 天前
Redis: Sentinel工作原理和故障迁移流程
redis·sentinel
弥琉撒到我2 天前
微服务JMeter解析部署使用全流程
jmeter·spring cloud·微服务·架构
kong79069282 天前
SpringCloud入门(十二)全局过滤器和跨域
spring cloud·gateway网关·全局过滤器