SpringCloud Alibaba之 Sentinel流量防卫兵

文章目录

  • Sentinel 流量防卫兵
    • 一、安装与部署
      • 1.1 服务端 JAR 包
      • 1.2 客户端挂载
      • 1.3 Sentinel Dashboard 监控
    • 二、流量控制
      • 2.1 流量控制算法
      • 2.2 流控规则
      • 2.3 @SentinelResource 对方法流控
      • 2.4 示例:对接口流控
      • 2.5 系统规则
    • 三、热点参数限流
    • 四、服务熔断和降级
      • 4.1 熔断规则:慢调用比例
      • 4.2 熔断规则:异常比例
      • 4.3 熔断规则:异常数
      • 4.4 精准服务降级
      • 4.5 远程调用中的服务熔断
    • 五、限流 / 熔断后的异常处理
      • 5.1 接口异常处理
      • 5.2 方法中 sentinel 异常的处理
      • 5.3 方法中其它异常的处理


提示:以下是本篇文章正文内容,SpringCloud Alibaba 系列学习将会持续更新

Spring Cloud Alibaba 官方学习文档
SpringCloud Alibaba之 Sentinel流量防卫兵_第1张图片

Sentinel 流量防卫兵

See the 中文文档 for document in Chinese.

经过之前的学习,我们了解了微服务存在的雪崩问题,也就是说一个微服务出现问题,有可能导致整个链路直接不可用,这种时候我们就需要进行及时的熔断和降级,这些策略,我们之前通过使用 Hystrix 来实现。

SpringCloud Alibaba 也有自己的微服务容错组件,但是它相比 Hystrix 更加的强大。

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

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
  • 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

一、安装与部署

1.1 服务端 JAR 包

它和 Nacos一样,它是独立安装和部署的,下载地址:https://github.com/alibaba/Sentinel/releases
SpringCloud Alibaba之 Sentinel流量防卫兵_第2张图片

注意下载下来之后是一个 jar 文件(其实就是个SpringBoot项目),我们需要在 IDEA 中部署:
SpringCloud Alibaba之 Sentinel流量防卫兵_第3张图片

启动之后,就可以访问到 Sentinel 的监控页面了,用户名和密码都是 sentinel,地址:http://localhost:8858
SpringCloud Alibaba之 Sentinel流量防卫兵_第4张图片

1.2 客户端挂载

这样就成功开启监控页面了,接着我们需要让我们的服务连接到 Sentinel 控制台,老规矩,导入依赖:

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

然后在配置文件中添加 Sentinel 相关信息(实际上 Sentinel 是本地在进行管理,但是我们可以连接到监控页面,这样就可以图形化操作了):

spring:
  application:
    name: userservice
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
      	# 添加监控页面地址即可
        dashboard: localhost:8858

1.3 Sentinel Dashboard 监控

现在启动我们的服务,然后访问一次服务,这样 Sentinel 中就会存在信息了(懒加载机制,不会一上来就加载):
在这里插入图片描述
SpringCloud Alibaba之 Sentinel流量防卫兵_第5张图片
现在我们就可以在 Sentinel 控制台中对我们的服务运行情况进行实时监控了,可以看到监控的内容非常的多,包括时间点QPS(每秒查询率)响应时间等数据。

按照上面的方式,我们将所有的服务全部连接到 Sentinel 管理面板中。

在这里插入图片描述

回到目录…

二、流量控制

前面我们完成了对 Sentinel 的搭建与连接,接着我们来看看Sentinel的第一个功能,流量控制。

我们的机器不可能无限制的接受和处理客户端的请求,如果不加以限制,当发生高并发情况时,系统资源将很快被耗尽。为了避免这种情况,我们就可以添加流量控制(也可以说是限流)。当一段时间内的流量到达一定的阈值的时候,新的请求将不再进行处理,这样不仅可以合理地应对高并发请求,同时也能在一定程度上保护服务器不受到外界的恶意攻击。

那么要实现限流,正常情况下,我们该采取什么样的策略呢?

  • 方案一:快速拒绝,既然不再接受新的请求,那么我们可以直接返回一个拒绝信息,告诉用户访问频率过高。
  • 方案二:预热,依然基于方案一,但是由于某些情况下高并发请求是在某一时刻突然到来,我们可以缓慢地将阈值提高到指定阈值,形成一个缓冲保护
  • 方案三:排队等待,不接受新的请求,但是也不直接拒绝,而是进队列先等一下,如果规定时间内能够执行,那么就执行,要是超时就算了。

2.1 流量控制算法

  1. 漏桶算法
    顾名思义,就像一个桶开了一个小孔,水流进桶中的速度肯定是远大于水流出桶的速度的,这也是最简单的一种限流思路:
    在这里插入图片描述
    我们知道,桶是有容量的,所以当桶的容量已满时,就装不下水了,这时就只有丢弃请求了。
    利用这种思想,我们就可以写出一个简单的限流算法。

  2. 令牌桶算法
    只能说有点像信号量机制。现在有一个令牌桶,这个桶是专门存放令牌的,每隔一段时间就向桶中丢入一个令牌(速度由我们指定)当新的请求到达时,将从桶中删除令牌,接着请求就可以通过并给到服务,但是如果桶中的令牌数量不足,那么不会删除令牌,而是让此数据包等待。
    SpringCloud Alibaba之 Sentinel流量防卫兵_第6张图片
    可以试想一下,当流量下降时,令牌桶中的令牌会逐渐积累,这样如果突然出现高并发,那么就能在短时间内拿到大量的令牌。

  3. 固定时间窗口算法
    我们可以对某一个时间段内的请求进行统计和计数,比如在14:15~14:16这一分钟内,请求量不能超过100,也就是一分钟之内不能超过 100次请求,那么就可以像下面这样进行划分:
    在这里插入图片描述
    虽然这种模式看似比较合理,但是试想一下这种情况:14:15:59的时候来了100个请求、14:16:01的时候又来了100个请求
    出现上面这种情况,符合固定时间窗口算法的规则,所以这 200个请求都能正常接受,但是,你应该发现了,我们其实希望的是 60秒内只有100个请求,但是这种情况却是在 3秒内出现了200个请求,很明显已经违背了我们的初衷。
    因此,当遇到临界点时,固定时间窗口算法存在安全隐患。

  4. 滑动时间窗口算法
    相对于固定窗口算法,滑动时间窗口算法更加灵活,它会动态移动窗口,重新进行计算:
    SpringCloud Alibaba之 Sentinel流量防卫兵_第7张图片
    虽然这样能够避免固定时间窗口的临界问题,但是这样显然是比固定窗口更加耗时的。

回到目录…

2.2 流控规则

了解完了我们的限流策略和判定方法之后,我们在 Sentinel 中进行实际测试一下,打开管理页面的簇点链路模块 -> 流控
SpringCloud Alibaba之 Sentinel流量防卫兵_第8张图片

这里演示对我们的图书接口进行限流,点击流控,会看到让我们添加流控规则

  • 阈值类型:QPS就是每秒钟的请求数量,并发线程数是按服务当前使用的线程数据进行统计的。
    在这里插入图片描述

  • 流控模式:当达到阈值时,流控的对象,这里暂时只用直接。
    直接:只针对于当前接口。
    关联:当其他接口超过阈值时,会导致当前接口被限流。
    链路:更细粒度的限流,能精确到具体的方法。
    SpringCloud Alibaba之 Sentinel流量防卫兵_第9张图片

  • 流控效果:就是我们上面所说的三种方案。
    SpringCloud Alibaba之 Sentinel流量防卫兵_第10张图片

回到目录…

2.3 @SentinelResource 对方法流控

上面我们学过的流控规则都是对某个接口进行的限流,这里我们讲解一下@SentinelResource 的使用,对某个方法进行限流

①我们先在控制层新增一个接口,但实际上和之前的接口内容一样,调用同样的方法。SpringCloud Alibaba之 Sentinel流量防卫兵_第11张图片

@SentinelResource 监控此方法,无论被谁执行都在监控范围内,这里给的 value 是自定义名称,这个注解可以加在任何方法上,包括 Controller 中的请求映射方法,跟 @HystrixCommand 贼像SpringCloud Alibaba之 Sentinel流量防卫兵_第12张图片

③我们这里创建两个请求映射,都来调用 Service 的被监控方法,需要配置它们单独控制:

spring:
  application:
    name: bookservice
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858
      # 关闭 Context 收敛,这样被监控方法可以进行不同链路的单独控制
      web-context-unify: false

SpringCloud Alibaba之 Sentinel流量防卫兵_第13张图片

④然后我们在 Sentinel 控制台中对该方法添加流控规则:
SpringCloud Alibaba之 Sentinel流量防卫兵_第14张图片

最后我们在浏览器中对 /book/{bid}/book2/{bid} 这两个接口都进行测试,会发现无论请求哪个接口,只要调用了 Service 中的getBookById(int bid) 这个方法,都会被限流。
SpringCloud Alibaba之 Sentinel流量防卫兵_第15张图片

回到目录…

2.4 示例:对接口流控

①QPS 阈值为1,流控模式: 直接,流控效果: 快速失败。

当我们快速地进行请求时 (每秒超过1次),会直接返回失败信息:
在这里插入图片描述

②QPS 阈值为3,流控模式: 直接,流控效果: Warm up 缓存预热。

这样的缓存预热可以在10秒内,将单机阈值提升到每秒3次。
SpringCloud Alibaba之 Sentinel流量防卫兵_第16张图片

③QPS 阈值为1,流控模式: 关联 /error,流控效果: 快速失败。

当我们快速地请求自带的/error接口时 (每秒超过1次),会关联的影响到我们的/book接口。
SpringCloud Alibaba之 Sentinel流量防卫兵_第17张图片

我们使用 PostMan 的 Runner 连续对关联资源发起请求:
SpringCloud Alibaba之 Sentinel流量防卫兵_第18张图片
开启Postman,然后我们会发现图书服务已经凉凉。当我们关闭掉 Postman 的任务后,恢复正常。
在这里插入图片描述

④QPS 阈值为1,流控模式: 链路,流控效果: 快速失败。

最后我们来讲解一下链路模式,它能够更加精准的进行流量控制。链路流控模式指的是当从指定接口过来的资源请求达到限流条件时,开启限流

我们在上面学习了@SentinelResource 对方法流控,这种方案会对调用该方法的 /book/{uid}/book2/{uid} 都进行限流。
而这个链路选项实际上就是决定只限流从哪个方向来的调用,比如我们只对/book2这个接口对getBook(int uid) 方法的调用进行限流,那么我们就可以为其指定链路:
SpringCloud Alibaba之 Sentinel流量防卫兵_第19张图片

此时我们会发现,限流效果只对我们配置的链路接口有效,而其他链路是不会被限流的。
SpringCloud Alibaba之 Sentinel流量防卫兵_第20张图片
回到目录…

2.5 系统规则

除了直接对接口进行限流规则控制之外,我们也可以根据当前系统的资源使用情况,决定是否进行限流:
SpringCloud Alibaba之 Sentinel流量防卫兵_第21张图片

系统规则支持以下的模式:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
在这里插入图片描述

回到目录…

三、热点参数限流

我们还可以对某一热点数据进行精准限流,比如在某一时刻,不同参数被携带访问的频率是不一样的:

  • http://localhost:8081/param?a=10 访问100次
  • http://localhost:8081/param?b=10 访问0次
  • http://localhost:8081/param?c=10 访问3次

由于携带参数a的请求比较多,我们就可以只对携带参数a的请求进行限流。

①这里我们创建一个新的测试请求映射:

@RestController
public class ParamController {
    @GetMapping("/param")
    @SentinelResource("getParam") // 必须添加该注解,才能设置参数精准限流
    public String getParamABC(@RequestParam(value = "a", required = false) String a,
                              @RequestParam(value = "b", required = false) String b,
                              @RequestParam(value = "c", required = false) String c) {
        return "{a = " + a + ", b = " + b + ", c = " + c + "}";
    }
}

②启动之后,我们在 Sentinel 的热点规则模块进行热点配置:
SpringCloud Alibaba之 Sentinel流量防卫兵_第22张图片

③然后开始访问我们的测试接口,分别携带3个参数进行超阈值请求:
SpringCloud Alibaba之 Sentinel流量防卫兵_第23张图片

④除了直接对某个参数精准限流外,我们还可以对参数携带的指定值单独设定阈值。
 比如我们可以对参数b限流阈值放宽到 20,但当参数b=8时,QPS 达到1就限流:
SpringCloud Alibaba之 Sentinel流量防卫兵_第24张图片

这样,将按照我们指定的特例进行限流
SpringCloud Alibaba之 Sentinel流量防卫兵_第25张图片

在这里插入图片描述

回到目录…

四、服务熔断和降级

还记得我们前所说的服务降级吗,也就是说我们需要在整个微服务调用链路出现问题的时候,及时对服务进行降级,以防止问题进一步恶化。
SpringCloud Alibaba之 Sentinel流量防卫兵_第26张图片
那么,各位是否有思考过,如果在某一时刻,服务B 出现故障(可能就卡在那里了),而这时服务A 依然有大量的请求,在调用服务B,那么,由于服务A 没办法再短时间内完成处理,新来的请求就会导致线程数不断地增加,这样,CPU 的资源很快就会被耗尽。

那么要防止这种情况,就只能进行隔离了,这里我们提两种隔离方案:

  1. 线程池隔离
    线程池隔离实际上就是对每个服务的远程调用单独开放线程池,比如服务A 要调用服务B,那么只基于固定数量的线程池,这样即使在短时间内出现大量请求,由于没有线程可以分配,所以就不会导致资源耗尽了。相当于让不同的服务调用,去各自的线程池中获取资源去请求,从而不会消耗其它服务调用的资源 和 CPU的资源。
    SpringCloud Alibaba之 Sentinel流量防卫兵_第27张图片
  2. 信号量隔离
    信号量隔离是使用 Semaphore 类实现的(如果不了解,可以观看本系列 并发编程篇 视频教程),思想基本上与上面是相同的,也是限定指定的线程数量能够同时进行服务调用,但是它相对于线程池隔离,开销会更小一些,使用效果同样优秀,也支持超时等。

    Sentinel 也正是采用的这种方案实现隔离的。

好了,说回我们的熔断和降级,当下游服务因为某种原因变得不可用或响应过慢时,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务而是快速返回或是执行自己的替代方案,这便是服务降级
SpringCloud Alibaba之 Sentinel流量防卫兵_第28张图片
整个过程分为三个状态:

  • 关闭:熔断器不工作,所有请求全部该干嘛干嘛。
  • 打开:熔断器工作,所有请求一律降级处理。
  • 半开:尝试进行一下下正常流程,要是还不行继续保持打开状态,否则关闭。

那么我们来看看 Sentinel 中如何进行熔断和降级操作,打开管理页面,我们可以自由新增熔断规则,其中熔断策略有三种模式:
SpringCloud Alibaba之 Sentinel流量防卫兵_第29张图片

回到目录…

4.1 熔断规则:慢调用比例

SpringCloud Alibaba之 Sentinel流量防卫兵_第30张图片
慢调用比例:如果出现那种半天都处理不完的调用,有可能就是服务出现故障,导致卡顿,这个选项是按照最大响应时间RT)进行判定。如果一次请求的处理时间超过了指定的 RT,那么就被判定为慢调用在一个统计时长内,如果请求数目大于最小请求数目,并且被判定为慢调用的请求比例已经超过阈值,将触发熔断。经过熔断时长之后,将会进入到半开状态进行试探(这里和Hystrix一致)

然后创建一个接口,来模拟一下慢调用:

@GetMapping("/slow")
public String slow() throws InterruptedException {
    Thread.sleep(500);
    return "这是一个慢比例调用!";
}

重启,然后我们创建一个新的熔断规则:
SpringCloud Alibaba之 Sentinel流量防卫兵_第31张图片

可以看到,熔断规则内是可以正常访问的:
SpringCloud Alibaba之 Sentinel流量防卫兵_第32张图片
但是突破熔断规则时,就会服务熔断:
SpringCloud Alibaba之 Sentinel流量防卫兵_第33张图片

回到目录…

4.2 熔断规则:异常比例

SpringCloud Alibaba之 Sentinel流量防卫兵_第34张图片
异常比例:这个与慢调用比例类似,不过这里判断的是出现异常的次数,与上面一样,我们也来进行一些小测试:

@GetMapping("/ecpPCT")
public String EcpPCT() {
    int n = (int) (Math.random() * 10);
    if(n % 2 == 0) {
        throw new RuntimeException("运行时异常: " + n);
    }
    return "异常比例测试";
}

启动服务器,接着添加我们的熔断规则:
SpringCloud Alibaba之 Sentinel流量防卫兵_第35张图片
现在我们进行访问,会发现后台疯狂报错,然后就熔断了:
SpringCloud Alibaba之 Sentinel流量防卫兵_第36张图片

回到目录…

4.3 熔断规则:异常数

异常数:这个和上面的唯一区别就是,只要达到指定的异常数量,就熔断,这里我们修改一下熔断规则:
SpringCloud Alibaba之 Sentinel流量防卫兵_第37张图片
现在我们再次不断访问此接口,可以发现,效果跟之前其实是差不多的,只是判断的策略稍微不同罢了:
在这里插入图片描述

回到目录…

4.4 精准服务降级

同样,Sentinel 也支持我们进行方法级别细粒度的熔断降级。
我们在需要控制的方法上添加 @SentinelResource 注解,可以配置 blockHandler 参数返回熔断后的代替方案。

@GetMapping("/test2")
@SentinelResource(value = "testMethod", blockHandler = "block")
public String testMethod() {
	throw new RuntimeException();
}

public String block(BlockException e) {
    return "发生服务降级/熔断了";
}

接着我们对进行熔断配置,注意是对我们添加的@SentinelResource中指定名称的testMethod进行配置:
SpringCloud Alibaba之 Sentinel流量防卫兵_第38张图片

OK,可以看到熔断降级之后的效果:
SpringCloud Alibaba之 Sentinel流量防卫兵_第39张图片

回到目录…

4.5 远程调用中的服务熔断

我们上面学的都是在一个微服务中,对接口或方法访问时,进行了降级和熔断。那此时,我们还需要知道在微服务之间的远程调用过程中,某个微服务出现问题导致无法访问时,我们该如何做熔断和降级呢?

我们以 borrowservice/borrow/{uid} 接口中的远程调用为例进行讲解吧!

方案一:OpenFeign 实现降级熔断:

  • Feign 集成了 Spring Cloud CircuitBreaker断路器,实现了熔断降级的功能。
  • 但是,之前我们在使用时发现,Feign 的降级需要依靠 Hystrix 组件来实现,所以那时我们的启动类依然需要用 @EnableHystrix 注解来修饰。
    参考往期文章:SpringCloud之 Hystrix服务熔断 的 OpenFeign 实现降级 模块
  • 其实,我们今天学习的 sentinel 也支持 feign 的使用,这样我们就不再需要废弃的 Hystrix 组件了。

①首先我们需要在配置文件中开启 sentinelfeign 的支持:

feign:
  sentinel:
    enabled: true

②我们给 borrowservice 中的 BookClient 接口创建替代实现类:

@Component
public class BookClientFallback implements BookClient {
    @Override
    public Book findBookById(int bid) {
        return new Book(-1, "代替方案", "");
    }
}

③为 BookClient 接口指定替代方案,使用 @FeignClient 注解的 fallback 属性

@FeignClient(value = "bookservice", fallback = BookClientFallback.class)
public interface BookClient {
    @GetMapping("/book/{bid}")
    Book findBookById(@PathVariable("bid") int bid);
}

④然后直接启动就可以了,中途的时候我们把图书服务全部下掉,可以看到正常使用替代方案:
在这里插入图片描述
这样 Feign 的配置就OK了,

方案二:@SentinelRestTemplate 实现降级熔断:

原本传统的 RestTemplate 需要借助 @SentinelRestTemplate注解实现:

@Bean
@LoadBalanced
@SentinelRestTemplate(blockHandler = "handleException", 
	  blockHandlerClass = ExceptionUtil.class,
      fallback = "fallback", 
      fallbackClass = ExceptionUtil.class) // 这里同样可以设定 fallback 等参数
public RestTemplate restTemplate() {
    return new RestTemplate();
}

这里就不多做赘述了。

在这里插入图片描述

回到目录…

五、限流 / 熔断后的异常处理

现在我们已经了解了如何进行限流服务熔断降级操作,那么这些状态下的返回结果该怎么修改呢,我们看到返回的是 Sentinel 默认的数据,现在我们希望自定义改如何操作?不仅仅是限流、服务降级熔断,只要是 Sentinel 包括的异常都可以处理。

5.1 接口异常处理

这里我们先创建好被限流状态下需要返回的内容,定义一个请求映射:

@Controller
public class BlockedController {
    @RequestMapping("/blocked")
    public JSONObject blocked(){
        JSONObject object = new JSONObject();
        object.put("code", 403);
        object.put("success", false);
        object.put("massage", "您的请求频率过快,请稍后再试!");
        return object;
    }
}

接着我们在配置文件中将此页面设定为限流页面:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858
      # 将刚刚编写的请求映射设定为限流页面
      block-page: /blocked

默认的返回结果:
在这里插入图片描述
修改后,当被限流时,就会被重定向到指定页面:
SpringCloud Alibaba之 Sentinel流量防卫兵_第40张图片

回到目录…

5.2 方法中 sentinel 异常的处理

那么,对于方法级别的限流呢?经过前面的学习我们知道,当某个方法被限流时,会直接在后台抛出异常,那么这种情况我们该怎么处理呢?
SpringCloud Alibaba之 Sentinel流量防卫兵_第41张图片
比如我们之前在 Hystrix 中可以直接添加一个替代方案,@HystrixCommand(fallbackMethod = "onError"),这样当出现异常时会直接执行我们的替代方法并返回,Sentinel 也可以。

比如我们还是在 getBookById(int bid) 方法上进行配置:注意blockHandler只能处理限流情况下抛出的异常

@Override
@SentinelResource(value = "getBook", blockHandler = "blocked") //监控此方法,无论被谁执行都在监控范围内,这里给的value是自定义名称,这个注解可以加在任何方法上,包括Controller中的请求映射方法,跟HystrixCommand贼像
public Book getBookById(int bid) {
    return bookMapper.getBookById(bid);
}

// 替代方案,注意参数和返回值需要保持一致,并且参数最后还需要额外添加一个 BlockException
public Book blocked(int bid, BlockException e) {
    return new Book(-1, "", "");
}

可以看到,一旦被限流将执行替代方案,最后返回的结果就是:
在这里插入图片描述

回到目录…

5.3 方法中其它异常的处理

如果是方法本身抛出的其他类型异常,不在blockHandler管控范围内,但是可以通过@SentinelResource的其它参数进行处理:

@RestController
public class FallbackController {

    @GetMapping("/test")
    @SentinelResource(value = "testFallback",
            fallback = "except",    // 指定异常时的替代方案
            blockHandler = "block", // 出现限流时的替代方案
            exceptionsToIgnore = IOException.class) // 可以忽视的异常,出现该异常时不使用替代方案
    public String testFallback() {
        throw new RuntimeException("出现了运行时异常");
    }

    // 替代方法必须和原方法返回值和参数一致,最后可以添加一个Throwable作为参数接受异常
    public String except(Throwable t) {
        return t.getMessage();
    }
}

我们给刚刚作了异常处理的方法,设置了流控:
SpringCloud Alibaba之 Sentinel流量防卫兵_第42张图片

这样,其它的异常也可以有替代方案了:
SpringCloud Alibaba之 Sentinel流量防卫兵_第43张图片
同样的,当超阈值访问时,Sentinel 的限流异常也可以处理:
在这里插入图片描述

特别注意

  • 如果在没有配置 blockHandler 的情况下,fallback 会将 Sentinel 机制内(限流、熔断)的异常也一并处理了。
  • 如果配置了 blockHandler,那么在出现限流/熔断时,依然只会执行 blockHandler指定的替代方案(因为限流是在方法执行之前进行的)。
在这里插入图片描述

回到目录…


总结:
提示:这里对文章进行总结:
本文是对Sentinel 流量防卫兵的学习,学习了 Sentinel 的安装与部署,还使用了它提供的功能:流量控制、服务降级熔断,并且还可以自定义sentinel异常的处理方案。之后的学习内容将持续更新!!!

你可能感兴趣的:(SpringCloud,spring,cloud,sentinel,流量控制,熔断降级)