目录
一、Sentinel简介
1.官网
2.Sentinel 是什么
3.Sentinel 的历史
4.Sentinel 基本概念
资源
规则
5.Sentinel 功能和设计理念
(1).流量控制
什么是流量控制
流量控制设计理念
(2).断降级
什么是熔断降级
熔断降级设计理念
(3).系统自适应保护
6.主要工作机制
7.流控降级与容错标准
8.下载地址:
9.Sentinel的特征
10.Sentinel的主要特性
11.面试题
讲讲什么是缓存穿透?击穿?雪崩?如何解决?
1、缓存穿透:
2、缓存雪崩:
3、缓存击穿:
服务雪崩
服务降级
服务熔断
服务限流
服务隔离
服务超时
二、安装Sentinel
组成
安装步骤
1.下载
2.运行命令
3.访问sentinel管理界面
三、微服务8401整合Sentinel入门案例
1.启动Nacos8848
2.启动Sentinel8080
3.新建微服务8401
(1).新创建子模块 cloudalibaba-sentinel-service8401
(2).添加pom依赖
(3).YML参数配置
(4).主启动类
(5).业务类FlowLimitController
4.启动8401微服务后查看sentienl控制台
四、流控规则
1.基本介绍
2.流控模式
(1).直接
(2).关联
(3).链路
3.流控效果
1. 直接 - 快速失败(默认的流控处理)
2 预热WarmUp
(1).限流 冷启动
(2).公式
(3).官网及源码
(4).官网WarmUp配置
(5).官网测试:
(6).官网应用场景:
3 排队等待
(1).解释
(2).修改FlowLimitController
(3).sentinel配置
(4).测试效果:
4.流控效果V2(并发线程数)
(1).sentinel配置
(2).Jmeter模拟多个线程并发+循环请求
(3).测试:
五、熔断规则
基本介绍
熔断策略
新增熔断规则实战
1. 慢调用比例
(1).解释
(2).名词解释
(3).触发条件+熔断状态
(4).测试示例
1).代码
2).配置
3).jmeter压测
4).结论
2. 异常比例
(1).解释
(2).测试示例
1).代码
2).配置
3).jemeter压测
4).结论
3.异常数
(1).解释
(2).测试示例
(1).代码
(2).配置
(3).jemeter压测
(4).结论
六、@SentinelResource注解
1.简介
2.源码说明
3.启动Nacos成功
4.启动Sentinel成功
5.按照rest地址限流+默认限流返回
(1).业务类RateLimitController
(2).Sentinel控制台配置
(3).测试
6.按SentinelResource资源名称限流+自定义限流返回
(1).微服务cloudalibaba-sentinel-service8401
(2).测试地址
(3).配置流控规则:
7.按SentinelResource资源名称限流+自定义限流返回+服务器降级处理
(1).微服务cloudalibaba-sentinel-service8401
(2).配置流控规则
(3).测试
七、热点规则
1.基本介绍
2.官网:
3.代码
4.配置
5.测试
6.参数例外项
特例情况
配置
测试
前提条件
八、授权规则
1.简介
2.官网
3.黑白名单示例
4.配置
5.测试
九、规则持久化
1.简介
Sentiel规则持久化三种模式分析
原始模式
Pull 模式
Push模式
自定义持久化
2.规则的种类
流量控制规则 (FlowRule)
熔断降级规则 (DegradeRule)
系统保护规则 (SystemRule)
访问控制规则 (AuthorityRule)
热点参数规则(ParamFlowRule)
3.配置持久化主要有以下原因:
4.单一持久化示例:
1).POM添加Nacos
2).YML参数配置
3).添加Nacos数据源配置
4).源代码
5).添加Nacos业务规则配置
6).重新启动8401再看sentine
5.全面持久化示例:
1).在Nacos中配置sentinel信息
2).配置信息
2.1 流控配置
2.2 熔断降级配置
2.3 热点参数配置
2.4 系统规则配置
2.5 授权规则配置
十、OpenFeign和Sentinel集成实现fallback服务降级
1.需求说明
2.程序解耦
前述参考
本例说明
3.编码步骤
(1).修改服务器提供方cloudalibaba-provider-payment9001
1).添加POM依赖
2).修改YML
3).主启动类
4).编写业务类
5).启动9001微服务自测一下
(2).修改cloud-api-commons
1).添加POM依赖
2).新增openFeign对外暴露接口
3).为新增远程调用新建全局统一服务降级类
(3).修改cloudalibaba-consumer-nacos-order84
1).添加POM依赖
2).YML参数配置
3).主启动类
4).业务类
(4).测试验证
1).9001正常启动后,再启动84通过feign调用
2).Sentinel流控为例,进行配置
3).9001宕机了,83通过feign调用
十一、GateWay和Sentinel集成实现服务限流
1.需求说明
2.启动nacos服务器8848
3.启动sentienl服务器8080
4.步骤
5.测试
一、Sentinel简介
面向分布式、多语言异构化服务架构的 流量治理组件
1.官网
等价对标Spring Cloud Circuit Breaker
2.Sentinel 是什么
3.Sentinel 的历史
- 2012 年,Sentinel 诞生,主要功能为入口流量控制。
- 2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量归整场景以及生产实践。
- 2018 年,Sentinel 开源,并持续演进。
- 2019 年,Sentinel 朝着多语言扩展的方向不断探索,推出 C++ 原生版本,同时针对 Service Mesh 场景也推出了 Envoy 集群流量控制支持
- 2020 年,推出 Sentinel Go 版本
- 2021 年,Sentinel 正在朝着 2.0 云原生高可用决策中心组件进行演进;同时推出了 Sentinel Rust 原生版本
- 2022 年,Sentinel 品牌升级为流量治理,领域涵盖流量路由/调度、流量染色、流控降级、过载保护/实例摘除等;同时社区将流量治理相关标准抽出到 OpenSergo 标准
4.Sentinel 基本概念
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
5.Sentinel 功能和设计理念
(1).流量控制
什么是流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示
流量控制设计理念
- 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
- 运行指标,例如 QPS、线程池、系统负载等;
- 控制的效果,例如直接限流、冷启动、排队等。
(2).断降级
什么是熔断降级
除了流量控制以外,及时对调用链路中的不稳定因素进行熔断也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求发生堆积,进而导致级联错误。

Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。
熔断降级设计理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。Hystrix 通过 线程池隔离 的方式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多),还需要预先给各个资源做线程池大小的分配。
- 通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
- 通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
(3).系统自适应保护
Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
6.主要工作机制
- 对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
- 根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel 提供开放的接口,方便您定义及改变规则。
- Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态。
7.流控降级与容错标准
Sentinel 社区正在将流量治理相关标准抽出到 OpenSergo 标准中,Sentinel 作为流量治理标准实现。有关 Sentinel 流控降级与容错 spec 的最新进展,请参考 opensergo-specification,也欢迎社区一起来完善标准与实现。

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

从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
11.面试题
讲讲什么是缓存穿透?击穿?雪崩?如何解决?
1、缓存穿透:
是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
2、缓存雪崩:
我们可以简单的理解为:由于原有缓存失效,新缓存未到 时间 (例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
3、缓存击穿:
某个 key 非常非常热,访问非常的频繁,高并发访问的情况下,当这个 key在失效(可能expire过期了,也可能LRU淘汰了)的瞬间,大量的请求进来,这时候就击穿了缓存,直接请求到了数据库,一下子来这么多,数据库肯定受不了,这就叫缓存击穿。某个key突然失效,然后这时候高并发来访问这个key,结果缓存里没有,都跑到db了。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以, 通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。

服务降级
服务降级,说白了就是一种服务托底方案,如果服务无法完成正常的调用流程,就使用默认的托底方案来返回数据。
例如,在商品详情页一般都会展示商品的介绍信息,一旦商品详情页系统出现故障无法调用时,会直接获取缓存中的商品介绍信息返回给前端页面。
服务熔断
- 闭合状态(保险丝闭合通电OK):服务一切正常,没有故障时,上游服务调用下游服务时,不会有任何限制。
- 开启状态(保险丝断开通电Error):上游服务不再调用下游服务的接口,会直接返回上游服务中预定的方法。
- 半熔断状态:处于开启状态时,上游服务会根据一定的规则,尝试恢复对下游服务的调用。此时,上游服务会以有限的流量来调用下游服务,同时,会监控调用的成功率。如果成功率达到预期,则进入关闭状态。如果未达到预期,会重新进入开启状态。
服务限流
服务限流就是限制进入系统的流量,以防止进入系统的流量过大而压垮系统。其主要的作用就是保护服务节点或者集群后面的数据节点,防止瞬时流量过大使服务和数据崩溃(如前端缓存大量实效),造成不可用;还可用于平滑请求, 类似秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
限流算法有两种,一种就是简单的请求总量计数,一种就是时间窗口限流(一般为1s),如令牌桶算法和漏牌桶算法就是时间窗口的限流算法。
服务隔离
有点类似于系统的垂直拆分,就按照一定的规则将系统划分成多个服务模块,并且每个服务模块之间是互相独立的,不会存在强依赖的关系。如果某个拆分后的服务发生故障后,能够将故障产生的影响限制在某个具体的服务内,不会向其他服务扩散,自然也就不会对整体服务产生致命的影响。互联网行业常用的服务隔离方式有:线程池隔离和信号量隔离。
服务超时
整个系统采用分布式和微服务架构后,系统被拆分成一个个小服务,就会存在服务与服务之间互相调用的现象,从而形成一个个调用链。形成调用链关系的两个服务中,主动调用其他服务接口的服务处于调用链的上游,提供接口供其他服务调用的服务处于调用链的下游。服务超时就是在上游服务调用下游服务时, 设置一个最大响应时间,如果超过这个最大响应时间下游服务还未返回结果,则断开上游服务与下游服务之间的请求连接,释放资源。
二、安装Sentinel
组成
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
Sentinel 社区官方网站: https://sentinelguard.io/Sentinel介绍网址: 介绍 · alibaba/Sentinel Wiki · GitHub
- 后台8719默认
- 前台8080开启
安装步骤
1.下载
Releases · alibaba/Sentinel · GitHub
sentinel-dashboard-1.8.6.jar
2.运行命令
- java环境已安装(jdk17已安装)
- 8080端口不能被占用
3.访问sentinel管理界面
- 登录账号密码均为sentinel
- 访问地址:http://localhost:8080

三、微服务8401整合Sentinel入门案例
1.启动Nacos8848
startup.cmd -m standalone访问地址: http://localhost:8848/nacos
2.启动Sentinel8080
java -jar sentinel-dashboard-1.8.6.jar访问地址: http://localhost:8080
3.新建微服务8401
(1).新创建子模块 cloudalibaba-sentinel-service8401
(2).添加pom依赖
<!--SpringCloud alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependencies>
<!--SpringCloud alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(3).YML参数配置
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
(4).主启动类
启动类添加@S pringBootApplication注解- springboot常用注解,以及 @EnableDiscoveryClient服务器注册与发现
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Main8401 {
public static void main(String[] args) {
SpringApplication.run(Main8401.class,args);
}
}
(5).业务类FlowLimitController
package com.atguigu.cloud.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
return "-----testB";
}
}
4.启动8401微服务后查看sentienl控制台
- http://localhost:8401/testA
- http://localhost:8401/testB

四、流控规则
1.基本介绍
Sentinel能够对流量进行控制,主要是监控应用的QPS流量或者并发线程数等指标,如果达到指定的阈值时,就会被流量进行控制,以避免服务被瞬时的高并发流量击垮,保证服务的高可靠性。参数见最下方:

1资源名
|
资源的唯一名称,默认就是请求的接口路径,可以自行修改,但是要保证唯一。
|
2针对来源
|
具体针对某个微服务进行限流,默认值为default,表示不区分来源,全部限流。
|
3阈值类型
|
QPS表示通过QPS进行限流,并发线程数表示通过并发线程数限流。
|
4单机阈值
|
与阈值类型组合使用。如果阈值类型选择的是QPS,表示当调用接口的QPS达到阈值时,进行限流操作。如果阈值类型选择的是并发线程数,则表示当调用接口的并发线程数达到阈值时,进行限流操作。
|
5是否集群
|
选中则表示集群环境,不选中则表示非集群环境。
|
2.流控模式
- 直接
- 关联
- 链路
(1).直接
默认流控模式,当接口达到限流条件时,直接开启限流功能。
表示1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误

(2).关联
- 当关联的资源达到阈值时,就限流自己
- 当与A关联的资源B达到阀值后,就限流A自己
B惹事,A挂了

版本:Apache JMeter 5.6.2 (Requires Java 8+)以上

(3).链路
来自不同链路的请求对同一个目标访问时,实施针对性的不同限流措施,比如C请求来访问就限流,D请求来访问就是OK
web-context-unify: false # controller
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务器注册中心
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
@SentinelResource(value = "common")
package com.atguigu.cloud.service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;
@Service
public class FlowLimitService {
@SentinelResource(value = "common")
public void common()
{
System.out.println("------FlowLimitService come in");
}
}
package com.atguigu.cloud.controller;
import com.atguigu.cloud.service.FlowLimitService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
return "-----testB";
}
@Resource private FlowLimitService flowLimitService;
@GetMapping("/testC")
public String testC()
{
flowLimitService.common();
return "------testC";
}
@GetMapping("/testD")
public String testD()
{
flowLimitService.common();
return "------testD";
}
}


3.流控效果
快速失败:单机阈值超过1秒,则直接失败。warm Up:单机阈值为10秒(需除以冷却因子3),预热时间为5秒(保护时间阈值为10/3 约为1秒三次),预热时间过后为最高阈值1秒10。排队等待:按照单机阈值为1秒,一秒钟通过一个请求,10秒后的请求作为超时处理,放弃。10秒的话一般在10、11条左右。
1. 直接 - 快速失败(默认的流控处理)
直接失败,抛出异常 Blocked by Sentinel (flow limiting)
2 预热WarmUp
(1).限流 冷启动
(2).公式
公式:阈值除以冷却因子coldFactor(默认值为3),经过预热时长后才会达到阈值
(3).官网及源码
地址: 流量控制 · alibaba/Sentinel Wiki · GitHub

默认 coldFactor 为3,即请求 QPS 从 threshold/3 开始,经预热时长逐渐升至设定的 QPS 阈值。

(4).官网WarmUp配置
默认 coldFactor 为 3,即请求QPS从(threshold / 3) 开始,经多少预热时长才逐渐升至设定的 QPS 阈值。
|
案例,单机阈值为10,预热时长设置5秒。
系统初始化的阈值为10 / 3 约等于3,即单机阈值刚开始为3(我们人工设定单机阈值是10,sentinel计算后QPS判定为3开始);
然后过了5秒后阀值才慢慢升高恢复到设置的单机阈值10,也就是说5秒钟内QPS为3,过了保护期5秒后QPS为10
|

(5).官网测试:
(6).官网应用场景:
3 排队等待
(1).解释
匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。详细文档可以参考 流量控制 - 匀速器模式,具体的例子可以参见 PaceFlowDemo。

注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
(2).修改FlowLimitController
@GetMapping("/testE")
public String testE()
{
System.out.println(System.currentTimeMillis()+" testE,排队等待");
return "------testE";
}
(3).sentinel配置
http://localhost:8401/testE
线程数20 1秒


按照单机阈值,一秒钟通过一个请求,10秒后的请求作为超时处理,放弃

(4).测试效果:

按照单机阈值,一秒钟通过一个请求,10秒后的请求作为超时处理,放弃,10秒的话一般在10、11、12条左右。
4.流控效果V2(并发线程数)
(1).sentinel配置

(2).Jmeter模拟多个线程并发+循环请求

(3).测试:
五、熔断规则
基本介绍

熔断策略
- 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
新增熔断规则实战
1.慢调用比例:例:1秒钟最小请求5个,超过超过20%比例,最大RT200毫秒的为慢调用,则进入熔断,熔断时间为5s,熔断时间过后在进行尝试恢复,成功则继续使用,恢复失败则在此进入熔断时长。调用比例0.1也就是为10分之一。2. 异常比例:例:1秒钟最小请求5个,超过20%的异常,则为异常比例调用,则进入熔断,熔断时间为5s,熔断时间过后在进行尝试恢复,成功则继续使用,恢复失败则在此进入熔断时长,调用比例0.2也就是为五分之一。3.异常数:例:1秒内最小请求5次,异常数达到1个,则进入熔断,熔断时间为5s,熔断时间过后在进行尝试恢复,成功则继续使用,恢复失败则在此进入熔断时长。
1. 慢调用比例
(1).解释
例:1秒钟最小请求5个,超过超过20%比例,最大RT200毫秒的为慢调用,则进入熔断,熔断时间为5s,熔断时间过后在进行尝试恢复,成功则继续使用,恢复失败则在此进入熔断时长。调用比例0.1也就是为10分之一。


(2).名词解释

(3).触发条件+熔断状态

1熔断状态(保险丝跳闸断电,不可访问):在接下来的熔断时长内请求会自动被熔断2探测恢复状态(探路先锋):熔断时长结束后进入探测恢复状态3结束熔断(保险丝闭合恢复,可以访问):在探测恢复状态,如果接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断,否则继续熔断。
(4).测试示例
1).代码
/**
* 新增熔断规则-慢调用比例
* @return
*/
@GetMapping("/testF")
public String testF()
{
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("----测试:新增熔断规则-慢调用比例 ");
return "------testF 新增熔断规则-慢调用比例";
}
2).配置

3).jmeter压测

4).结论


2. 异常比例
(1).解释


(2).测试示例
1).代码
/**
* 新增熔断规则-异常比例
* @return
*/
@GetMapping("/testG")
public String testG(){
System.out.println("----测试:新增熔断规则-异常比例");
int age= 10/0;
return "------testG,新增熔断规则-异常比例";
}
2).配置
- 不配置Sentinel,对于int age=10/0,调一次错一次报错error,页面报【Whitelabel Error Page】或全局异常
- 配置Sentinel,对于int age=10/0,如符合如下异常比例启动熔断,页面报【Blocked by Sentinel (flow limiting)】
例:1秒钟最小请求5个,超过20%的异常,则为异常比例调用,进行熔断,熔断时间5s,熔断时间过后在进行尝试恢复,成功则继续使用,恢复失败则在此进入熔断时长,调用比例0.2也就是为五分之一。

3).jemeter压测

4).结论




3.异常数
(1).解释


(2).测试示例
(1).代码
/**
* 新增熔断规则-异常数
* @return
*/
@GetMapping("/testH")
public String testH()
{
System.out.println("----测试:新增熔断规则-异常数 ");
int age = 10/0;
return "------testH,新增熔断规则-异常数 ";
}
(2).配置
例:1秒内最小请求5次,异常数达到1则,进行熔断,熔断时间结束后尝试进行恢复。恢复则继续使用,未恢复则继续等待熔断时长,在进行尝试。

(3).jemeter压测

(4).结论


六、@SentinelResource注解
1.简介
SentinelResource是一个流量防卫防护组件注解用于指定防护资源,对配置的资源进行流量控制、熔断降级等功能。
2.源码说明
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
//资源名称
String value() default "";
//entry类型,标记流量的方向,取值IN/OUT,默认是OUT
EntryType entryType() default EntryType.OUT;
//资源分类
int resourceType() default 0;
//处理BlockException的函数名称,函数要求:
//1. 必须是 public
//2.返回类型 参数与原方法一致
//3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置blockHandlerClass ,并指定blockHandlerClass里面的方法。
String blockHandler() default "";
//存放blockHandler的类,对应的处理函数必须static修饰。
Class<?>[] blockHandlerClass() default {};
//用于在抛出异常的时候提供fallback处理逻辑。 fallback函数可以针对所
//有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
//1. 返回类型与原方法一致
//2. 参数类型需要和原方法相匹配
//3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置fallbackClass ,并指定fallbackClass里面的方法。
String fallback() default "";
//存放fallback的类。对应的处理函数必须static修饰。
String defaultFallback() default "";
//用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常进
//行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求:
//1. 返回类型与原方法一致
//2. 方法参数列表为空,或者有一个 Throwable 类型的参数。
//3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置fallbackClass ,并指定 fallbackClass 里面的方法。
Class<?>[] fallbackClass() default {};
//需要trace的异常
Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
//指定排除忽略掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。
Class<? extends Throwable>[] exceptionsToIgnore() default {};
}
3.启动Nacos成功
startup.cmd -m standalone
4.启动Sentinel成功
java -jar sentinel-dashboard-1.8.8.jar
5.按照rest地址限流+默认限流返回
(1).业务类RateLimitController
@RestController
@Slf4j
public class RateLimitController {
@GetMapping("/rateLimit/byUrl")
public String byUrl(){
return "按rest地址限流测试OK";
}
}
(2).Sentinel控制台配置


(3).测试

6.按SentinelResource资源名称限流+自定义限流返回
不想用默认的限流提示(Blocked by Sentinel(flow limiting)),想返回 自定义限流的提示。@SentinelResource(value = "byResourceSentinelResource",blockHandler = "handleException")资源名称----byResourceSentinelResource自定义限流返回-----handleException
(1).微服务cloudalibaba-sentinel-service8401
@GetMapping("/rateLimit/byResource")
@SentinelResource(value = "byResourceSentinelResource",blockHandler = "handleException")
public String byResource()
{
return "按资源名称SentinelResource限流测试OK";
}
public String handleException(BlockException exception)
{
return "服务不可用@SentinelResource启动"+"\t"+"o(╥﹏╥)o";
}
(2).测试地址
(3).配置流控规则:

设置流控时选择的不是地址而是@SentinelResource value值进行参数设置。



7.按SentinelResource资源名称限流+自定义限流返回+服务器降级处理
按SentinelResource配置,点击超过限流配置返回自定义限流提示+程序异常返回fallback服务降级@SentinelResource(value = "doActionSentinelResource",blockHandler = "doActionBlockHandler", fallback = "doActionFallback")资源名称--------------doActionSentinelResource自定义限流返回-----doActionBlockHandler程序异常---------------fallback
(1).微服务cloudalibaba-sentinel-service8401
@GetMapping("/rateLimit/doAction/{p1}")
@SentinelResource(value = "doActionSentinelResource",
blockHandler = "doActionBlockHandler", fallback = "doActionFallback")
public String doAction(@PathVariable("p1") Integer p1) {
if (p1 == 0){
throw new RuntimeException("p1等于零直接异常");
}
return "doAction";
}
public String doActionBlockHandler(@PathVariable("p1") Integer p1,BlockException e){
log.error("sentinel配置自定义限流了:{}", e);
return "sentinel配置自定义限流了";
}
public String doActionFallback(@PathVariable("p1") Integer p1,Throwable e){
log.error("程序逻辑异常了:{}", e);
return "程序逻辑异常了"+"\t"+e.getMessage();
}
(2).配置流控规则
设置流控时选择的不是地址而是@SentinelResource value值进行参数设置。

(3).测试
http://localhost:8401/rateLimit/doAction/2
http://localhost:8401/rateLimit/doAction/0
- blockHandler,主要针对sentinel配置后出现的违规情况处理
- fallback,程序异常了JVM抛出的异常服务降级
- 两者可以同时共存
七、热点规则
1.基本介绍2.官网3.代码4.配置5.测试6.参数例外项
1.基本介绍

2.官网:
3.代码
/**
* 热点参数限流示例
* @param p1
* @param p2
* @return
*/
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value="p1",required = false)String p1,@RequestParam(value = "p2",required = false)String p2)
{
return "----testHotKey";
}
public String dealHandler_testHotKey(String p1,String p2,BlockException exception){
return "----dealHandler_testHotKey";
}
4.配置

限流模式只支持QPS模式,固定写死了。(这才叫热点)@SentinelResource注解的方法 参数索引, 0代表第一个参数,1代表第二个参数,以此类推单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。
- 方法testHotKey里面第一个参数P1只要QPS超过每秒1次,马上降级处理
- http://localhost:8401/testHotKey
5.测试
- http://localhost:8401/testHotKey?p1=abc
- 含有参数P1,当每秒访问的频率超过1次时,会触发Sentinel的限流操作
- http://localhost:8401/testHotKey?p1=abc&p2=33
- 含有参数P1且包括其他参数,当每秒访问的频率超过1次时,也会触发Sentinel的限流操作
- http://localhost:8401/testHotKey?p2=abc
- 没有热点参数P1,不断访问则不会触发限流操作
6.参数例外项
上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流参数例外项:当参数等于特定某个值时,参数阈值会发生变化,其他值时仍然会被。
特例情况
- 含有P1参数,超过1秒钟一个后,达到值1后马上被限流
- 我们期望p1参数当它是某个特殊值时,到达某个约定值后【普通正常限流】规则突然例外、失效了,它的限流值和平时不一样
- 假如当p1的值等于5时,它的阈值可以达到200或其它值
配置


测试
- http://localhost:8401/testHotKey?p1=5
- 超过1秒钟一个后,达到阈值200后才会被限流
- 当p1等于5的时候,阈值变为200
- http://localhost:8401/testHotKey?p1=3
- 超过1秒钟一个后,达到阈值后马上被限流
- 当p1不等于5的时候,阈值就是平常的【普通正常限流】规则
前提条件
热点参数的注意点,参数必须是基本类型或者String
八、授权规则
1.简介
调用方信息通过 ContextUtil.enter(resourceName, origin) 方法中的 origin 参数传入。
2.官网
官网地址: 黑白名单控制 · alibaba/Sentinel Wiki · GitHub
3.黑白名单示例
演示授权规则,黑白名单静止
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Empower授权规则,用来处理请求的来源
*/
@RestController
@Slf4j
public class EmpowerController {
@GetMapping(value = "/empower")
public String requestSentinel4(){
log.info("测试Sentinel授权规则empower");
return "Sentinel授权规则";
}
}
调用方信息通过 ContextUtil.enter(resourceName, origin) 方法中的 origin 参数传入。如何在实际应用中设置:RequestOriginParser (转换请求参数类)可以转换ip、用户、appName等。我们需要重写该类中的parseOrigin方法来说实现 origin参数的传入,告诉httpServletRequest携带的是什么参数,是黑名单还是白名单,放行还是静止。
package com.atguigu.cloud.controller.handle;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
/**
* RequestOriginParser 中的- parseOrigin方法来说实现 origin参数的传入,告诉httpServletRequest携带的是什么参数,是黑名单还是白名单,放行还是静止。
*/
@Component
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
return httpServletRequest.getParameter("serverName");
}
}
4.配置

5.测试
- http://localhost:8401/empower?serverName=test
- Blocked by Sentinel (flow limiting)
- http://localhost:8401/empower?serverName=test2
- Blocked by Sentinel (flow limiting)
- http://localhost:8401/empower?serverName=ab
- 访问正常 返回参数:Sentinel授权规则
九、规则持久化
1.简介
Sentiel规则持久化三种模式分析
推送模式
|
说明
|
优点
|
缺点
|
原始模式
|
API 将规则推送至客户端并直接更新到内存中,扩展写数据源(WritableDataSource)
|
简单,无任何依赖
|
不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境
|
Pull 拉取模式
|
扩展写数据源(WritableDataSource), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等,还需要实现文件的读数据源(ReadableDataSource)
|
简单,无任何依赖;规则持久化
|
不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。
|
Push 推送模式
|
扩展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。
|
规则持久化;一致性;快速
|
引入第三方依赖
|
原始模式
- 在这种模式下,规则是直接通过 Sentinel 控制台定义,并且通过 Sentinel 的 API 推送到客户端。规则被保存在客户端的内存中,因此如果客户端重启,规则就会丢失。这种方式不适合生产环境,因为它缺乏持久化能力。

- 在控制台界面新增规则后。
- 将规则存储到内存中:通过InMemoryRuleRepositoryAdapter#save() 存储到内存中。
- 将规则发布到客户端:通过SentinelApiClient#executeCommand() 发起异步的http调用,利用的是HttpClient发起的http调用。
- Http请求的路径就是Sentinel客户端的ServerSocket监听的端口。
- sentinel-transport-common-1.8.0.jar这个jar包是用来实现控制台和客户端的通信的jar。
- CommandCenter的实现类SimpleHttpCommandCenter的start()方法会创建ServerSocket,默认8719端口,用来实时监听sentinel-dashboard发送过来的请求。
- 客户端解析sentinel dashboard发送的请求数据,解析为不同类型检验规则。
- 将规则更新到客户端内存中:DynamicSentinelProperty#updateValue()
- 将规则持久化到数据源中,但是这个数据源是空的,没有实现,这是一个扩展点,实现持久化。WritableDataSource#write()
Pull 模式
- 在 Pull 模式中,客户端会定期从一个规则管理中心(如数据库、文件系统或其他配置中心)拉取最新的规则。这种方式可以保证规则的持久化,但是需要客户端主动去拉取规则,可能会引入额外的网络延迟,并且需要谨慎配置拉取频率以避免性能问题。
- WritableDataSource
- 写数据源的实现类:FileWritableDataSource
- ReadableDataSource
- 读数据源的实现类:FileRefreshableDataSource
- 读数据源的功能:监听文件数据的变化,及时的更新到Sentinel客户端。实现原理是FileRefreshableDataSource的父类AutoRefreshDataSource数据源内部新建了一个定时任务,每隔3000ms就判断一次文件是否改变。

Push模式
- Push 模式是 Sentinel 推荐的一种持久化方式,它通过一个中央管理系统(如 Nacos、Apollo、Zookeeper、Redis 等)来管理规则,并将规则推送到客户端。这种方式可以实现实时性较好的规则更新,同时减少了客户端的轮询负担。
- 控制台推送规则:将规则推送到Nacos或其他远程配置中心。Sentinel客户端链接Nacos,获取规则配置;并监听Nacos配置变化,如发生变化,就更新本地缓存(从而让本地缓存总是和Nacos一致)
- 控制台监听Nacos配置变化,如发生变化就更新本地缓存(从而让控制台本地缓存总是和Nacos一致)

自定义持久化
- Sentinel允许开发人员编写自己的DataSource适配器来与不同的持久化存储系统集成。
- 提供高度的灵活性,可以与各种外部系统(如数据库、缓存系统等)集成,实现规则的动态加载和更新。
- 需要配置Sentinel与外部系统的连接,并编写必要的代码来处理规则的加载和更新。
2.规则的种类
- 流量控制规则 FlowRule
- 熔断降级规则 DegradeRule
- 系统保护规则 SystemRule
- 访问控制规则 AuthorityRule
- 热点规则 ParamFlowRule
流量控制规则 (FlowRule)
Field
|
说明
|
默认值
|
resourceName
|
资源名,资源名是限流规则的作用对象
| |
limitApp
|
流控针对的调用来源,若为 default 则不区分调用来源
|
default,代表不区分调用来源
|
grade
|
限流阈值类型,QPS 模式(1)或并发线程数模式(0)
|
QPS 模式
|
count
|
限流阈值
| |
strategy
|
调用关系限流策略:直接、链路、关联
|
根据资源本身(直接)
|
controlBehavior
|
流量控制效果(直接拒绝、Warm Up、匀速排队)
|
直接拒绝
|
clusterMode
|
是否集群限流
|
否
|
private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule1 = new FlowRule();
rule1.setResource(resource);
// Set max qps to 20
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
熔断降级规则 (DegradeRule)
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() 方法来用硬编码的方式定义流量控制规则。
private static void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule(resource);
.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType());
.setCount(0.7); // Threshold is 70% error ratio
.setMinRequestAmount(100)
.setStatIntervalMs(30000) // 30s
.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
if (newState == State.OPEN) {
// 变换至 OPEN state 时会携带触发时的值
System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),
TimeUtil.currentTimeMillis(), snapshotValue));
} else {
System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),
TimeUtil.currentTimeMillis()));
}
});
系统保护规则 (SystemRule)
Field
|
说明
|
默认值
|
highestSystemLoad
|
load1
触发值,用于触发自适应控制阶段
|
-1 (不生效)
|
avgRt
|
所有入口流量的平均响应时间
|
-1 (不生效)
|
maxThread
|
入口流量的最大并发数
|
-1 (不生效)
|
qps
|
所有入口资源的 QPS
|
-1 (不生效)
|
highestCpuUsage
|
当前系统的 CPU 使用率(0.0-1.0)
|
-1 (不生效)
|
private void initSystemProtectionRule() {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10);
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
访问控制规则 (AuthorityRule)
- resource:资源名,即限流规则的作用对象
- limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
- strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式
热点参数规则(ParamFlowRule)
属性
|
说明
|
默认值
|
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
阈值的限制。
仅支持基本类型和字符串类型
| |
clusterMode
|
是否是集群参数流控规则
|
false
|
clusterConfig
|
集群流控相关配置
|
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setParamIdx(0)
.setCount(5);
// 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
.setClassType(int.class.getName())
.setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
3.配置持久化主要有以下原因:
- 数据安全性:持久化配置可以保证在系统或者应用重启后,重要的配置数据不会丢失,可以确保数据的安全性和稳定性。
- 数据可恢复性:持久化配置可以在数据丢失或者损坏时进行恢复,保证系统的正常运行。
- 支持分布式系统:对于分布式系统来说,配置的持久化可以确保各个节点的一致性,避免因为节点的临时变动导致的问题。
- 可扩展性:持久化配置易于进行扩展和修改,可以适应不同的应用场景和业务需求。
- 提高系统性能:通过实现配置的持久化,可以有效减少读取配置文件的次数,提高系统的运行效率。
- 降低耦合性:持久化配置可以使得应用和配置之间松散耦合,方便系统的维护和升级。
4.单一持久化示例:
修改cloudalibaba-sentinel-service84011.POM2.YML3.添加Nacos业务规则配置 快速访问测试接口4.停止8401再看sentinel5.重新启动8401再看sentine
1).POM添加Nacos
<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu.cloud</groupId>
<artifactId>mscloudV5</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudalibaba-sentinel-service8401</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2).YML参数配置
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务器注册中心
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
datasource: #数据持久化规则以json的方式进行存储到nacos中
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务器注册中心
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType
3).添加Nacos数据源配置
rule-type: flow
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
- 流量控制规则 FlowRule
- 熔断降级规则 DegradeRule
- 访问控制规则 AuthorityRule
- 系统保护规则 SystemRule
- 热点规则 ParamFlowRule
4).源代码


5).添加Nacos业务规则配置

[
{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
- resource:资源名称;
- limitApp:来源应用;
- grade:阈值类型,0表示线程数,1表示QPS;
- count:单机阈值;
- strategy:流控模式,0表示直接,1表示关联,2表示链路;
- controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
- clusterMode:是否集群。


- 停止8401再看sentinel

6).重新启动8401再看sentine
5.全面持久化示例:
1).在Nacos中配置sentinel信息
flux-control: # 流控管理(这个名称可以自定义)
nacos: # 告诉sentinel用nacos作为数据源
data-id: feign-test_flux-control_config.json # 配置中心里执行文件的dataId
server-addr: localhost:8848 # nacos的地址
rule-type: flow # 指定文件配置的是那种规则
degrade-control: # 熔断管理(这个名称可以自定义)
nacos:
data-id: feign-test_degrade-control_config.json
server-addr: localhost:8848
rule-type: degrade
param-flow-control: # 热点参数管理(这个名称可以自定义)
nacos:
data-id: feign_test-hot_flux-config.json
server-addr: localhost:8848
rule-type: param-flow
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务器注册中心
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
datasource: # sentinel用nacos作为数据源的配置
flux-control: # 流控管理(这个名称可以自定义)
nacos: # 告诉sentinel用nacos作为数据源
data-id: feign-test_flux-control_config.json # 配置中心里执行文件的dataId
server-addr: localhost:8848 # nacos的地址
rule-type: flow # 指定文件配置的是那种规则
degrade-control: # 熔断管理(这个名称可以自定义)
nacos:
data-id: feign-test_degrade-control_config.json
server-addr: localhost:8848
rule-type: degrade
param-flow-control: # 热点参数管理(这个名称可以自定义)
nacos:
data-id: feign_test-hot_flux-config.json
server-addr: localhost:8848
rule-type: param-flow
- data-id:需要告诉sentinel读取配置中心中的哪个配置文件。
- rule-type:告诉sentinel配置文件配置的控制规则,flow:流控、degrade:熔断、param-flow热点参数,想看有哪些规则参数可以查看com.alibaba.cloud.sentinel.datasource包下的枚举类:RuleType。
public enum RuleType {
FLOW("flow", FlowRule.class),
DEGRADE("degrade", DegradeRule.class),
PARAM_FLOW("param-flow", ParamFlowRule.class),
SYSTEM("system", SystemRule.class),
AUTHORITY("authority", AuthorityRule.class),
GW_FLOW("gw-flow", "com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"),
GW_API_GROUP("gw-api-group", "com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition");
//省略部分代码
}
2).配置信息
2.1 流控配置
[
{
"resource": "/test", // 资源名
"limitApp": "default", // // 针对来源,若为 default 则不区分调用来源
"grade": 1, // 限流阈值类型(1:QPS; 0:并发线程数)
"count": 1, // 阈值
"clusterMode": false, // 是否是集群模式
"controlBehavior": 0, // 流控效果 (0:快速失败; 1:Warm Up(预热模式); 2:排队等待)
"strategy": 0, // 流控模式(0:直接; 1:关联; 2:链路)
"warmUpPeriodSec": 10, // 预热时间(秒,预热模式需要此参数)
"maxQueueingTimeMs": 500, // 超时时间(排队等待模式需要此参数)
"refResource": "rrr" // 关联资源、入口资源(关联、链路模式)
}
]

2.2 熔断降级配置
- 防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”。
- 当某个服务提供者发生故障的时候,向调用方返回一个错误响应或者替代响应,而不是让调用方等待超时。
[
{
"resource": "/degrade",
"grade": 0, // 熔断策略,支持慢调用比例(0),异常比例(1),异常数(2)策略
"count": 1000, // 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用,单位ms);异常比例/异常数模式下为对应的阈值
"slowRatioThreshold": 0.1,// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
"minRequestAmount": 10, //熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
"timeWindow": 10, // 熔断时长,单位为 s
"statIntervalMs": 1000 // 统计时长(单位为 ms),如 60*1000 代表分钟级
}
]

2.3 热点参数配置
nacosNacos是由阿里巴巴开源的服务治理中间件,集成了动态服务发现、配置管理和服务元数据管理功能,广泛应用于微服务架构中,简化服务治理过程。项目地址: GitCode - 全球开发者的开源社区,开源代码托管平台
[
{
"resource": "/test1",
"grade": 1, // 限流模式(QPS 模式,不可更改)
"paramIdx": 0, // 参数索引
"count": 13, // 单机阈值
"durationInSec": 6, // 统计窗口时长
"clusterMode": false, // 是否集群 默认false
"controlBehavior": 0, // 流控效果(支持快速失败和匀速排队模式)
"limitApp": "default",
// 高级选项
"paramFlowItemList": [{
"classType": "int", // 参数类型
"count": 222, // 限流阈值
"object": "2" // 参数值
}]
}
]

2.4 系统规则配置
[
{
"avgRt": 1, // RT
"highestCpuUsage": -1, // CPU 使用率
"highestSystemLoad": -1, // LOAD
"maxThread": -1, // 线程数
"qps": -1, // 入口 QPS
"count": 55, // 阈值,在CPU使用率中是百分比
}
]

2.5 授权规则配置
[
{
"resource": "sentinel_spring_web_context",
"limitApp": "/test",
"strategy": 0 // 授权类型(0代表白名单;1代表黑名单。)
}
]

十、OpenFeign和Sentinel集成实现fallback服务降级
1.需求说明2.程序解耦3.编码步骤4.测试验证
1.需求说明
1 84 通过OpenFeign调用 9001微服务,正常访问OK2 84 通过OpenFeign调用 9001微服务, 异常访问error访问者要有fallback服务降级的情况,不要持续访问9001加大微服务负担,但是通过feign接口调用的又方法各自不同,如果每个不同方法都加一个fallback配对方法,会导致代码膨胀不好管理,工程埋雷....../(ㄒoㄒ)/~~3 public @ interface FeignClient通过fallback属性进行统一配置,feign接口里面定义的 全部方法都走统一的服务降级 , 一个搞定即可 。4 9001微服务自身还带着sentinel内部配置的流控规则,如果满足也会被触发,也即本例有2个Case4.1 OpenFeign接口的统一fallback服务降级处理4.2 Sentinel访问触发了自定义的限流配置,在注解@SentinelResource里面配置的blockHandler方法。
2.程序解耦
前述参考

本例说明

3.编码步骤
startup.cmd -m standalone
java -jar sentinel-dashboard-1.8.8.jar
1.编写9001服务提供方,主要编写业务内容。2.将服务纳入到 openfeign( cloud-api-commons)中进行管理,并对外暴露服务9001外所提供的服务接口。3.消费者通过openfeign( -api-commons)进行调用服务,在调用的过程中需要fallBack服务器降级则进行降级,该进行流量监控则进行流量监控。1.编写9001服务提供方,主要编写业务内容。2.将服务纳入到 openfeign( cloud-api-commons)中进行管理,并对外暴露服务9001外所提供的服务接口。3.消费者通过openfeign( api-commons)进行调用服务,在调用的过程中需要fallBack服务降级则进行降级(降级的编码是在 api-commons中),该进行流量监控则进行流量监控。
(1).修改服务器提供方cloudalibaba-provider-payment9001
1).添加POM依赖
重点依赖:
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--SpringBoot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2).修改YML
配置sentinel参数
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard 控制台服务器地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
3).主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Main9001
{
public static void main(String[] args)
{
SpringApplication.run(Main9001.class,args);
}
}
4).编写业务类
controller
package com.atguigu.cloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.cloud.entities.PayDTO;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.resp.ReturnCodeEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
@RestController
public class PayAlibabaController {
@GetMapping("/pay/nacos/get/{orderNo}")
@SentinelResource(value = "getPayByOrderNo",blockHandler = "handlerBlockHandler")
public ResultData getPayByOrderNo(@PathVariable("orderNo")String orderNo)
{
//模拟从数据库查询出数据并赋值给DTO
PayDTO payDTO= new PayDTO();
payDTO.setId(1024);
payDTO.setOrderNo(orderNo);
payDTO.setAmount(BigDecimal.valueOf(9.9));
payDTO.setUserId(1);
return ResultData.success("查询返回值:"+payDTO);
}
public ResultData handlerBlockHandler(@PathVariable("orderNo")String orderNo, BlockException exception)
{
return ResultData.fail(ReturnCodeEnum.RC500.getCode(), "getPayByOrderNo服务器不可用,"+"触发sentinel流控配置规则"+"\t"+"o(╥﹏╥)o");
}
/*
fallback服务降级方法纳入到Feign接口统一处理,全局一个
public ResultData myFallBack(@PathVariable("orderNo") String orderNo,Throwable throwable)
{
return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"异常情况:"+throwable.getMessage());
}
*/
}
5).启动9001微服务自测一下
http://localhost:9001/pay/nacos/get/ord1024
(2).修改cloud-api-commons
1).添加POM依赖
重点依赖:
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--SpringBoot通用依赖模块 actuator 是spring boot提供的对应用系统的自省和监控的集成功能,可以对应用系统进行配置查看、相关功能统计等-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
2).新增openFeign对外暴露接口
PayFeignSentinelApi
package com.atguigu.cloud.apis;
import com.atguigu.cloud.resp.ResultData;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* openFeign 与Sentinel整合-open调用服务提供者如9001,
* 服务器调用失败,找allback 进行处理全局fallback处理服务器降级
*/
@FeignClient(value = "nacos-payment-provider",fallback = PayFeignSentinelApiFallBack.class)
public interface PayFeignSentinelApi
{
@GetMapping("/pay/nacos/get/{orderNo}")
public ResultData getPayByOrderNo(@PathVariable("orderNo")String orderNo);
}
3).为新增远程调用新建全局统一服务降级类
fallback = PayFeignSentinelApiFallBack.class
package com.atguigu.cloud.apis;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.resp.ReturnCodeEnum;
import org.springframework.stereotype.Component;
/**
* 为新增远程调用新建全局统一服务降级类 fallback = PayFeignSentinelApiFallBack.class
*/
@Component
public class PayFeignSentinelApiFallBack implements PayFeignSentinelApi
{
@Override
public ResultData getPayByOrderNo(String orderNo) {
return ResultData.fail(ReturnCodeEnum.RC500.getCode(), "对方服务器宕机或不可用,fallBack服务降级o(╥﹏╥)o");
}
}
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
(3).修改cloudalibaba-consumer-nacos-order84
1).添加POM依赖
重点依赖:
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2024</artifactId>
<groupId>com.atguigu.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-consumer-nacos-order84</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.atguigu.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2).YML参数配置
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
service-u
#消费者将要去访问的微服务名称(nacos微服务提供者叫什么你写什么)
service-url:
nacos-user-service: http://nacos-payment-provider
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
3).主启动类
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
public class Main84 {
public static void main(String[] args) {
SpringApplication.run(Main84.class,args);
}
}
4).业务类
orderNacosController
package com.atguigu.cloud.controller;
import com.atguigu.cloud.apis.PayFeignSentinelApi;
import com.atguigu.cloud.resp.ResultData;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderNacosController
{
@Resource
private PayFeignSentinelApi payFeignSentinelApi;
/**
* 消费着调用openFeign封装的接口(PayFeignSentinelApi)
*/
@GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")
public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo)
{
return payFeignSentinelApi.getPayByOrderNo(orderNo);
}
}
(4).测试验证
- 业务模块测试正常访问
- 自动降级测试是否起效
- 服务降级是否起效
1).9001正常启动后,再启动84通过feign调用
测试业务模块是否正常访问服务提供者:测试正常http://localhost:9001/pay/nacos/get/ord1024

消费者:调用成功http://localhost:84/consumer/pay/nacos/get/ord1024

2).Sentinel流控为例,进行配置
测试自动降级是否起效图形界面进行配置

- http://localhost:84/consumer/pay/nacos/get/ord1024
- 频繁访问后触发了Sentinel的流控规则 blockHandler起效

3).9001宕机了,83通过feign调用
- 测试83调用9001,此时故意关闭9001微服务提供者,看84消费侧自动降级,不会被耗死
- 降级效果

十一、GateWay和Sentinel集成实现服务限流
1.需求说明2.启动nacos服务器88483.启动sentienl服务器80804.步骤5.测试
1.需求说明
2.启动nacos服务器8848
startup.cmd -m standalone
3.启动sentienl服务器8080
java -jar sentinel-dashboard-1.8.8.jar
4.步骤
(1).建Module(2).改POM(3).写YML(4).业务类(5).主启动(6).业务类
cloudalibaba-sentinel-gateway9528
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2024</artifactId>
<groupId>com.atguigu.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-sentinel-gateway9528</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server:
port: 9528
spring:
application:
name: cloudalibaba-sentinel-geteway # sentinel+gataway整合Case
cloud:
nacos:
discovery:
server-addr: localhost:8080
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
url: https://localhost:9001 #匹配后提供服务的路由地址
predicates:
- Path=/pay/** # 断言,路径相匹配的进行路由
package com.atguigu.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Main9528 {
public static void main(String[] args) {
SpringApplication.run(Main9528.class,args);
}
}
gateway网关配置自定义路由规则,限流返回值定制1.自定义sentinel路由规则:控、熔断、热点、授权2.自定了限流返回参数定制:BlockRequestHandler
package com.atguigu.cloud.config;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import org.springframework.http.codec.ServerCodecConfigurer;
import javax.annotation.PostConstruct;
import java.util.*;
@Configuration
public class GatewayConfiguration
{
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer)
{
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct //javax.annotation.PostConstruct
public void doInit() {
initBlockHandler();
}
//=========================================================================================以上为网关默认配置
/**
* =================================================================gateway网关配置自定义
* gateway网关配置自定义路由规则,限流返回值定制
* 1.自定义sentinel路由规则:控、熔断、热点、授权
* 2.自定了限流返回参数定制:BlockRequestHandler
*/
private void initBlockHandler()
{
Set<GatewayFlowRule> rules = new HashSet<>();
//可在此添加多过自定义规则要与 Gateway routes中的id相对应,规则参数为sentinel中的流控、熔断、热点、授权等规则。
rules.add(new GatewayFlowRule("pay_routh1")
.setCount(2)//根据流控参数进行定义规则
.setIntervalSec(1)
);
//可在此添加多过自定义规则要与 Gateway routes中的id相对应
// rules.add(new GatewayFlowRule("httpbin_route")
GatewayRuleManager.loadRules(rules);//将编写的sentinel路由规则加载到网关中.
BlockRequestHandler handler = new BlockRequestHandler() {//设置的自定义限流响应值定制
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String, String> map = new HashMap<>();
map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());//访问太多
map.put("errorMessage","请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(handler);//gateway回调方法-添加设置的自定义限流响应值定制
}
}
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
}

- setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException。
- Sentinel 网关流控默认的粒度是 route 维度以及自定义 API 分组维度,默认不支持 URL 粒度。若通过 Spring Cloud Alibaba 接入,请将 spring.cloud.sentinel.filter.enabled 配置项置为 false(若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false)。
- 若使用 Spring Cloud Alibaba Sentinel 数据源模块,需要注意网关流控规则数据源类型是 gw-flow,若将网关流控规则数据源指定为 flow 则不生效。
5.测试
- 服务模块原生url访问:http://localhost:9001/pay/nacos/333
- 加网关模块(gateway)url:http://localhost:9528/pay/nacos/333 点击时:1秒没超过2次 正常
- sentinel+gateway:加快点击频率,出现限流容错
点击时:1秒超过2次,触发网关配置的sentinel路由规则,进入网关自定义限流返回值
