• sentinel介绍和使用


    背景

    在微服务架构中,我们的业务是拆分成一个一个的单体服务,一个服务调用另一个服务时,请求不断发送,如果出现网络波动或者故障,延迟处理,请求就会不断堆积,最终可能造成系统的瘫痪,经典案例就是服务雪崩。

    服务雪崩

    在分布式系统中,由于网络原因或自身的原因,服务一般无法保证100%可用,单个实例故障时,处理请求缓慢或者没有响应,导致上层调用它的服务实例也变慢,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这种由单个服务引发的级联故障称为服务雪崩。

    造成雪崩原因可以归结为以下三个:

    1. 服务提供者不可用(硬件故障,程序bug,缓存击穿,用户大量请求)
    2. 重试加大流量(用户重试,代码逻辑重试)
    3. 服务调用者不可用(同步等待造成的资源耗尽)

    常见的服务容错模式

    超时

    在上游服务调用下游服务时,设置一个最大响应时间,如果超过这个时间,下游未作出反应,就断开请求,释放掉线程。

    熔断模式

    服务响应慢或⼤量超时熔断该服务,后续调⽤直接返回,直到⽬标服务出现好转。

    这种模式主要是参考电路熔断,如果⼀条线路电压过⾼,保险丝会熔断,防⽌⽕灾。放到我们的系统中,如果某个⽬标服务调⽤慢或者有⼤量超时,此时,熔断该服务的调⽤,对于后续调⽤请求,不在继续调⽤⽬标服务,直接返回,快速释放资源。如果⽬标服务情况好转则恢复调⽤。

    隔离模式

    不同业务使⽤不同线程池,不同业务间的请求互不影响,某⼀类业务耗尽线程池资源,后续请求直接返回。

    这种模式就像对系统请求按类型划分成⼀个个⼩岛的⼀样,当某个⼩岛被⽕少光了,不会影响到其他的⼩岛。例如可以对不同类型的请求使⽤线程池来资源隔离,每种类型的请求互不影响,如果⼀种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调⽤后续资源。这种模式使⽤场景⾮常多,例如将⼀个服务拆开,对于重要的服务使⽤单独服务器来部署。

    限流模式

    对应⽤QPS有⼀个合理的预期,⾼于预期阀值时,后续请求会直接返回。

    上述的熔断模式和隔离模式都属于出错后的容错处理机制,⽽限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最⾼的QPS阈值,若⾼于设置的阈值则对该请求直接返回,不再调⽤后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。

    降级模式

    服务降级是当服务器压⼒剧增的情况下,根据实际业务情况及流量,对⼀些服务和⻚⾯有策略的不处理或换种简单的⽅式处理,从⽽释放服务器资源以保证核⼼交易的能正常运⾏。

    服务降级主要⽤于当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运⾏,将⼀些 不重要 或 不紧急 的服务或任务进⾏服务的 延迟使⽤ 或 暂停使⽤。

    例如,B站部分服务器某⼀时刻突发⽹络故障,⼤量请求⼀下⼦转移到剩余正常的集群节点上,导致服务器超负荷运转,各个组件均⽆法正常访问,这时候就需要使⽤降级模式,在故障恢复之前,优先保障视频服务、⽀付等核⼼组件⼯作正常,⽽直播、搜索、动态等次要组件降级,请求延迟或快速返回。

    解决方案

    常见的容错组件:

    • Hystrix:由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者是第三方库,防止级联失败,从而提升系统的可用性和容错性。
    • Resilience4J:是一款轻量级、简单、文档清晰、丰富的熔断工具,这也是Hystrix官方推荐的替代产品,不仅如此,Resilience4J还原生支持SpringBoot,而且监控也支持和promettheus等多款主流产品进行整合。
    • Sentinel:阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。

    这里主要介绍 Sentinel

    Sentinel

    Sentinel 介绍

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

    轻量级的流量控制,熔断降级Java库。

    Sentinel的特征

    • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
    • 完备的实时监控:Sentinel 同时提供实时的监控功能。
    • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 SpringCloud、Dubbo、gRPC 的整合。
    • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。可以通过实现扩展接口来快速地定制逻辑。

    Sentinel组成

    • 控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。基于Spring boot 开发,打包后可以直接运行,不需要额外的Tomcat等web容器。
    • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。

    Sentinel 基本概念

    资源

    资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。

    只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

    规则

    围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

    响应时间(RT)

    响应时间是指系统对请求作出响应的时间。

    吞吐量(Throughput)

    指系统在单位时间内处理请求的数量。

    并发用户数

    是指系统可以同时承载的正常使用系统功能的用户的数量。

    QPS

    Queries Per Second 每秒请求数量。

    Sentinel主要功能

    流量控制

    流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。

    Sentinel 作为一个调配器,流量控制有以下几个角度:

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

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

    熔断降级

    什么是熔断降级

    除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。

    Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。

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

    • 通过并发线程数进行限制
    • 通过响应时间对资源进行降级

    系统负载保护

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

    Sentinel 是如何工作的

    Sentinel 的主要工作机制如下:

    • 对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
    • 根据预设的规则,结合对资源的实时统计信息,对流量进行控制。
    • Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态。

    简单使用

    获取 sentinel 控制台

    从 release 页面 下载最新版本的控制台 jar 包 sentinel-dashboard.jar

    启动控制台

    启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。

    java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
    
    • 1

    其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080。

    注意:只有1.6.0及以上版本,才有这个简单的登录页面。默认用户名和密码都是sentinel。对于用户登录的相关配置可以在启动命令中增加下面的参数来进行配置:

    • -Dsentinel.dashboard.auth.username=sentinel: 用于指定控制台的登录用户名为 sentinel;
    • -Dsentinel.dashboard.auth.password=123456: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel
    • -Dserver.servlet.session.timeout=7200: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟。

    本地启动,访问:localhost:8080,输入账户密码登录后,可以看到如下页面:
    在这里插入图片描述
    登录成功后
    在这里插入图片描述

    项目整合Sentinel

    添加依赖

    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    增加配置

    # actuator
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    spring:
      cloud:
        sentinel:
          transport:
            dashboard: localhost:8080 # dashboard 控制台地址
            # 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
            # client-ip: 
          eager: true # 默认情况下 sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包,取消sentinel控制台懒加载功能
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试controller

    @RestController
    public class TestController{
    	@GetMapping("/list")
    	public String test(){
    		return "sentinel test"; 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动项目,访问 /list 可以看到
    在这里插入图片描述
    可以看到服务已经注册到sentinel 上了。

    使用 Sentinel 控制规则推送

    流控规则

    点击“簇点链路”菜单,然后在需要添加流控规则的资源点击“+流控”按钮弹出流控规则设置弹窗。
    在这里插入图片描述
    阈值类型中QPS表示每秒访问的次数,线程数表示同时可以访问的线程的数量,单机阈值则位具体的数据,如图所示:表示每秒只允许访问1次,超过1次会报异常。
    在这里插入图片描述

    流控高级选项

    点击之前保存的流控规则的编辑按钮,并打开高级选项
    在这里插入图片描述

    直接模式

    默认的流控模式,直接限制资源名的QPS或者线程数

    关联模式

    在这里插入图片描述
    编辑关联资源 /list1 ,并点击保存按钮。
    此时表示,如果 /list1 的访问 QPS 超过1,则 /list 会被sentinel限流(即 /list1 超量,/list 限流)。

    测试代码

    @RestController
    public class TestController {
    
        @Autowired
        private ConsumerHelloServiceImpl consumerHelloService;
    
        @GetMapping("/list")
        public String list(){
            consumerHelloService.test();
            return "sentinel list";
        }
    
        @GetMapping("/list1")
        public String list1(){
            consumerHelloService.test();
            return "sentinel list1";
        }
    
        @SneakyThrows
        public static void main(String[] args) {
            RestTemplate template = new RestTemplate();
            while (true){
                String forObject = template.getForObject("http://localhost:8090/list1", String.class);
                Thread.sleep(500);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    链路模式

    之前我们都是基于 controller 层的限流,sentinel同样支持 颗粒度更细的从 controller 到 service 层的限流。

    配置文件 yaml 增加配置:让Sentinel 源码中 CommonFilter 中的 WEB_CONTEXT_UNIFY 参数为 false,将其配置为 false 即可根据不同的URL 进行链路限流,如果不配置将不会生效。

    spring:
      cloud:
        sentinel:
          # 配置为false
          web-context-unify: false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    新增 service 方法

    @Service
    public class ConsumerHelloServiceImpl{
    	@SentinelResource("test")
    	public void test(){
    		System.out.println("test");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用 @SentinelResource 注解

    Controller 代码

    @RestController
    public class TestController {
    
        @Autowired
        private ConsumerHelloServiceImpl consumerHelloService;
    
        @GetMapping("/list")
        public String list(){
            consumerHelloService.test();
            return "sentinel list";
        }
    
        @GetMapping("/list1")
        public String list1(){
            consumerHelloService.test();
            return "sentinel list1";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    重启项目后,在浏览器访问几次 /list 和 /list1 ,可以在sentinel控制台上看到
    在这里插入图片描述
    在任意的一条 test 记录所在行点击流控按钮,选择链路流控模式,入口资源编辑成 / list1
    在这里插入图片描述
    此时相当于限制了 TestController.list1 -> ConsumerHelloServiceImpl.test 这条链路,而 TestController.list -> ConsumerHelloServiceImpl.test 这条链路没有被限制,可分别频繁访问 /list 和 /list1 测试,发现 /list1 这条路径已经被限流,而 /list可以随意访问无限制。

    流控效果

    直接拒绝

    当QPS或线程数超过规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出 FlowExcepion。这种方式使用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。

    Warm Up

    当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动“,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。例如在系统刚刚启动的时候,系统可能有很多初始化工作要处理,加载大量的缓存等,这时候大量的请求过来,容易把系统压垮,需要一个冷处理过程,慢慢提高系统的处理请求能力。

    匀速排队

    严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的时漏桶算法。这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

    使用 sentinel 进行降级

    在这里插入图片描述

    熔断策略

    慢调用比例 ( SLOW_REQUEST_RATIO ): 选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于则统计为慢调用。当单位统计时长( statIntervalMs 默认1秒)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

    在这里插入图片描述

    异常比例 ( ERROR_RATIO ): 当单位统计时长( statIntervalMs 默认1秒 )内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有异常,则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0] ,代表 0% - 100%。

    在这里插入图片描述

    异常数 ( ERROR_COUNT ):当单位统计时长内(默认1秒)的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALFOPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

    使用 sentinel 进行热点限流

    在这里插入图片描述

    • 热点规则是特殊的流控规则,只能支持QPS模式的流控。
    • 参数索引表示想要进行热点参数控制的参数位于方法入参中的位置。
    • 单机阈值含义同流控规则中的单机阈值。

    在这里插入图片描述

    • 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面单机阈值的限制。仅支持基本类型和字符串类型。
    • 需要注意,参数例外值仅支持基本类型和字符串类型,但是热点参数的热点,还是支持任意类型的。比如,我们使用类A接收入参,当接收的类A中的属性值完全相同时,才会计入此参数的QPS。
    • 如果参数对象是Object:根据该对象是否 equals 来确定是否同一个value,或需要自定义实现 ParamFlowArgument 接口
    • 如果对象是 Collection:循环校验其中每个元素
    • 如果对象是 Array:循环校验其中每个元素

    使用 sentinel 系统规则

    在这里插入图片描述

    Load

    当系统load1(1分钟平均负载)超过阈值,且并发线程数超过系统容量时触发,建议设置为系统CPU核心数 * 2.5;仅对Linux/Unix系统有效。

    其中的load1,可以在Linux系统上通过命令 uptime 查看:
    在这里插入图片描述
    这个命令返回3个值,分别为load1、load5、load15,表示系统1分钟的平均负载、5分钟的平均负载、15分钟的平均负载。

    其中的系统容量,含义如下所示:

    在这里插入图片描述

    RT

    所有入口流量的平均 RT达到 阈值触发

    线程数

    所有入口流量的并发线程数达到阈值触发

    入口QPS

    所有入口流量的平均QPS达到阈值触发

    相关源码所在位置:
    com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkSystem

    CPU使用率

    例如,设定CPU使用率为20%(即0.2),当接入应用所在机器的CPU使用率超过0.2之后,默认情况下会收到response code=429,content=Blocked by Sentinel (flow limiting)的返回。

    使用 sentinel 授权规则

    在这里插入图片描述
    授权规则的作用是限制指定来源(origin)的请求对指定资源的访问。有白名单和黑名单两种方式。

    • 白名单:来源(origin)在白名单内的调用者允许访问
    • 黑名单:来源(origin)在黑名单内的调用者不允许访问

    Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源的。

    public interface RequestOriginParser {
        /**    
         * 从请求request对象中获取origin,获取方式自定义
         */
        String parseOrigin(HttpServletRequest request);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例-给网关添加请求头

    在调用者服务中添加代码:

    @Component
    public class HeaderOriginParser implements RequestOriginParser {
        @Override
        public String parseOrigin(HttpServletRequest request) {
            // 1.获取请求头
            String origin = request.getHeader("origin");
            // 2.非空判断
            if (StringUtils.isEmpty(origin)) {
                origin = "blank";
            }
            return origin;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    既然获取请求origin的方式是从reques-header中获取origin值,我们必须让所有从gateway路由到微服务的请求都带上origin头。

    这个需要利用GatewayFilter来实现,AddRequestHeaderGatewayFilter。

    修改gateway服务中的application.yml,添加一个defaultFilter:

    spring:
      cloud:
        gateway:
          default-filters:
            - AddRequestHeader=origin,gateway
          routes:
           # ...略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样,从gateway路由的所有请求都会带上origin头,值为gateway。而从其它地方到达微服务的请求则没有这个头。

    对需要防护的资源增加相应的授权规则,即可达到拒绝访问的效果。

    BlockException

    在 Sentinel 中所有流控降级相关的异常都是异常类 BlockException 的子类:

    • 流控异常:FlowException
    • 熔断降级异常:DegradeException
    • 系统保护异常:SystemBlockException
    • 热点参数限流异常:ParamFlowException

    @SentinelResource 注解

    Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。

    注意:注解方式埋点不支持 private 方法。

    @SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

    • value:资源名称,必需项(不能为空)

    • entryType:entry 类型,可选项(默认为 EntryType.OUT)

    • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

    • fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:

      • 返回值类型必须与原函数返回值类型一致;
      • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
      • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:

      • 返回值类型必须与原函数返回值类型一致;
      • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
      • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

    特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

    代码示例:

    public class TestService {
    
        // 原函数
        @SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
        public String hello(long s) {
            return String.format("Hello at %d", s);
        }
        
        // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
        public String helloFallback(long s) {
            return String.format("Halooooo %d", s);
        }
    
        // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
        public String exceptionHandler(long s, BlockException ex) {
            // Do some log here.
            ex.printStackTrace();
            return "Oops, error occurred at " + s;
        }
    
        // 这里单独演示 blockHandlerClass 的配置.
        // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 public static 函数.
        @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
        public void test() {
            System.out.println("Test");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    sentinel 结合 gateway使用

    Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。
    在这里插入图片描述

    添加依赖

    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加配置

    spring:
      application:
        name: gateway3-service
      cloud:
        sentinel:
          transport:
            dashboard: localhost:8080
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动gateway 项目

    注:通过 Spring Cloud Alibaba Sentinel 自动接入的 API Gateway 整合则无需此参数
    -Dcsp.sentinel.app.type=1

    可以在sentinel控制台上看到
    在这里插入图片描述

    Sentinel 从 1.6.0 版本开始,提供了 Spring Cloud Gateway 的适配模块,可提供两种资源维度的限流:

    • route 维度:在 Spring 配置 路由条目时,资源名为 routeId
    • 自定义 API 维度,用户可以用 Sentinel 提供的 API 来定义一些 API 分组

    Sentinel 网关流控默认的粒度是 route 维度以及自定义 API 分组维度,默认不支持 URL 粒度。若通过 Spring Cloud Alibaba 接入,请将 spring.cloud.sentinel.filter.enabled 配置项置为 false(若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false)。

    在这里插入图片描述

    route维度

    route维度比较好理解,就是根据网关中配置的路由配置作为资源名

    API分组

    API分组就是对接口进行分组,然后对不同组的接口,实施不同的限流策略。

    添加API分组

    对API进行限流,需要先对API进行分组。如下图所示:

    在这里插入图片描述
    配置模式:精确、前缀和正则三种模式。

    • 精确模式是指对URL的路径完全匹配时,进行限流。例如,匹配串配置为 /order/1
    • 前缀模式是指对URL的路径前缀匹配时,进行限流。例如,匹配串配置为 /order/*
    • 正则模式是指对URL的路径符合正则表示式规则时,进行限流。例如,匹配串配置为 /order/\d*
  • 相关阅读:
    The DAO事件始末
    CVE-2022-31137 Roxy-WI未经身份验证的远程代码执行漏洞复现
    RabbitMQ-主题模式
    writev()与readv()
    从零开始:使用 Kubernetes 部署 Nginx 应用
    前端性能优化:启用 gzip
    计算机网络-网络层(IPV4地址,网络转化技术NAT,子网划分和子网掩码,无分类编址CIDR,构成超网,最长前缀匹配)
    ElasticSearch报错解决
    离散数学复习:二元关系
    Vue2利用创建a标签实现下载本地静态文件到本地电脑上的功能
  • 原文地址:https://blog.csdn.net/hundan_520520/article/details/126143096