springCloud/Alibaba常用中间件之Setinel实现熔断降级
文章目录
- SpringCloud Alibaba:
- 依赖版本补充
- Sentinel:
- 1、下载-运行:Sentinel(1.8.6)
- 下载sentinel:
- 运行:Sentinel <br>
- 2、流控规则
- ① 公共的测试代码以及需要使用的测试Jmeter
- ①、流控模式
- 1. 直接:
- 2. 并联:
- 3. 链路:
- ②、流控效果
- 1. 快速失败<br>
- 2. Warm Up(预热处理)
- 3. 排队等待
- ③、并发线程数
- 3、熔断规则
- 基础测试代码
- ①、慢调用比留策略
- ②、异常比例策略
- ③、异常数策略
- @SentinelResource注解
- 4、热点规则
- 5、授权规则
- RequestOriginParser部分**源码分析**
- 我们直接看到```AbstractSentinelInterceptor```这个拦截器,中的preHandler(请求前)方法中
- 6、规则的持久化
- 前言
- 代码基本配置
- 7、OpenFeign与Sentinel集成实现fallback服务降级
- 代码实现演示:
- 8、GateWay与Sentinel集成实现集体服务限流
SpringCloud Alibaba:
官方学习文档(中文): https://spring-cloud-alibaba-group.github.io/github-pages/2022/zh-cn/2022.0.0.0-RC2.html
微服务的中间件介绍与使用
微服务架构体系图:
依赖版本补充
下面所有代码中的依赖版本如下:
<properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><hutool.version>5.8.22</hutool.version><lombok.version>1.18.26</lombok.version><druid.version>1.1.20</druid.version><mybatis.springboot.version>3.0.2</mybatis.springboot.version><mysql.version>8.0.11</mysql.version><swagger3.version>2.2.0</swagger3.version><mapper.version>4.2.3</mapper.version><fastjson2.version>2.0.40</fastjson2.version><persistence-api.version>1.0.2</persistence-api.version><spring.boot.test.version>3.1.5</spring.boot.test.version><spring.boot.version>3.2.0</spring.boot.version><spring.cloud.version>2023.0.0</spring.cloud.version><spring.cloud.alibaba.version>2023.0.0.0-RC1</spring.cloud.alibaba.version><knife4j-openapi3.version>4.4.0</knife4j-openapi3.version> </properties>
Sentinel:
Sentinel是用来应对 高并发 的情况,这里的概念和前文章 《springCloud/Alibaba常用中间件》中的LoadBalancer 相似,这里就不多讲了。
与 Resilience4j 它不同的是 Sentinel 有图形化界面进行动态的操作,使得操作便捷方便
1、下载-运行:Sentinel(1.8.6)
下载sentinel:
官方下载链接:https://github.com/alibaba/Sentinel/releases (这里在官网上下载可能会很慢,可以使用下面的网盘链接)
网盘链接: https://pan.baidu.com/s/1UtS7ltnSeKKwz1nkNvwBGw?pwd=chyb 提取码: chyb
运行:Sentinel
到sentinel的jar包目录下运行
sentinel-dashboard-1.8.6.jar -jar
,这里的jar包名称根据实际名称来
测试:打开网址http://localhost:8080(默认启动网址)
默认登录账号密码都是:sentinel
2、流控规则
sentinel中的流控模式有:直接、并联、链路。其中搭配中流控效果( 快速失败、Warm Up、排队等待 )可以应对大部分的限流操作
① 公共的测试代码以及需要使用的测试Jmeter
1、创建model导入依赖
<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><!--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>
2、修改配文件(application.yml)和启动类
server:port: 8402
spring:application:name: cloudAlibaba-sentinelTest-servicecloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口dashboard: localhost:8080 #sentinel的地址
@SpringBootApplication
@EnableDiscoveryClient
public class Main8402 {public static void main(String[] args) {SpringApplication.run(Main8402.class, args);}
}
3、创建测试controller类
@RestController
/*流量限制控制器*/
public class FlowLimitController {@GetMapping("/testA")public String testA() {return "------testA";}@GetMapping("/testB")public String testB() {return "------testB";}
}
4、测试
请求一下http://localhost:8402/testB
或者 http://localhost:8402/testA
注意:这里一定要请求一下,否则可能不会显示,因为sentinel是一个 懒加载 要是没有请求的话它是不会自动取进行监测的
然后在去sentinel中的主页就可以看到有服务了且在实时监测中有两个请求
性能测试Jmeter下载
JMeter下载及安装(附插件及中文包超详细)
①、流控模式
1. 直接:
当接口达到限流条件的话,直接开启 限流(也就是相当于开启断路器中的 OPEN状态 )
列如:配置/testA当在一秒内超过两次以上就直接开启 限流
开始配置:
QPS(Queries Per Second):每秒请求数
测试当访问/testA过快时便会
Blocked by Sentinel(flow limiting)
2. 并联:
当某一个接口达到限流条件时,指定关联的那一个接口开启 限流
列如:配置/testB当在一秒内超过两次以上就开启/testA的 限流
测试:当访问/testB达到限流条件时,访问testA
3. 链路:
根据某一个资源的请求路径进行设置 流控规则
这里为了需要使用注解@SentinelResource大家先用着,下面在单独领出来进行解释
修改测试代码:
application.yml
#....
# spring.cloud.sentinel.web-context-unify
web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
controller
@RestController
/*流量限制控制器*/
public class FlowLimitController {@Resourceprivate FlowLimitService flowLimitService;@GetMapping("/testC")public String testC() {flowLimitService.common();return "------testC";}@GetMapping("/testD")public String testD() {flowLimitService.common();return "------testD";}
}
在新建一个service层
@Service
public class FlowLimitService {/*这里的value可以理解为资源名,只要接口中有使用的这个接口都可以直接使用这个作为资源进行统一设置限流规则*/@SentinelResource(value = "common")public void common() {System.out.println("------FlowLimitService come in");}
}
配置Sentinel(配置之前先将/testC和/testD请求一下)
测试:快速请求/testC和/testD查看请求情况
当以/testC进行请求时会有一个一秒QPS只有一次的规则限制
②、流控效果
1. 快速失败
当违反流控返回Sentinel中默认的流控处理:
Blocked by Sentinel (flow limiting)
(这里后面也是可以进行修改的)
这里了就不演示了,上面的测试都是使用的这个
2. Warm Up(预热处理)
Warm Up 状态的触发依赖于 冷启动阶段的流量控制规则配置,通过动态调整阈值实现流量的平滑过渡。[简单来说就是当很久都没有请求时,面对突然的请求会触发预热处理]
在 预热时长 期间内会根据 coldFactor(冷因子【默认是3】) 和QPS的 threshold(单机阀值) , 单机阀值为:
threshold/coldFactor
例如:一直请求知道预热时长结束,就会发现不会再出发 流控 了,当然也不排除请求过快,1秒10次也会触发
预热时只会放出:10(单机阀值)/3(冷因子),时长为:10s
3. 排队等待
当 QPS 达到阀值时,后米的请求不会直接挂掉,而是会进入到排队等待~ms,当过滤时长之后,还没有请求到的话便会才会挂掉
简单的说:QPS 超阈值时,请求进入队列等待;按固定间隔时间放行请求;超时未处理的请求会被拒绝。
优点是:这种机制能在保护系统的同时,减少请求的直接丢弃,适用于需要平滑处理流量的高并发场景。
列如:
扩展:所用的核心算法是 漏桶算法 (可以参考:《springCloud/Alibaba常用中间件》## 标题文章下的CircuitBreaker断路器-Resilience4j-ratelimit(限流)
目录)
③、并发线程数
控制统一时间的线程数,当超过固定值时便会进行 限流
例如:
此时使用Jmeter来帮助我们模拟并发线程的情况
启动之后在访问http://localhost/testA 则基本上不会请求成功
但是要是不开启Jmeter只有一个请求量时,不管你的请求速度有多块都不会限流
3、熔断规则
基础测试代码
@RestController
/*测试熔断规则*/
public class CircuitBreakerController {@GetMapping("/testF")public String testF() {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}return "----------testF";}@GetMapping("/testG")public String testG() {int a = 1 / 0;return "----------testF";}
}
①、慢调用比留策略
根据你所定义的 根据指定 统计时长 内的指定的 最小请求数,去判断有多少慢调用(依据为:最大 RT),
最后计算比例是否大于 比例阈值,大于则进入熔断,经历 熔断时长 过后则会进入 HALF-OPEN(半开启状态)…(这里参考前面文章的CircuitBreaker断路器概念)
例如下面的Sentinel配置:
1000ms内请求大于5个,且慢调用(请求时长超过200ms的都视为慢调用)的比例超过0.1,则进入熔断且熔断时长为5s,
之后就是进入 HALF-OPEN(半开启状态)
名词解释:
- 调用:一个请求发送到服务器,服务器给与响应,一个响应就是一个调用。
- 最大RT:即最大的响应时间,指系统对请求作出响应的业务处理时间。
- 慢调用:处理业务逻辑的实际时间>设置的最大RT时间,这个调用叫做慢调用。
- 慢调用比例:在所以调用中,慢调用占有实际的比例=慢调用次数➗总调用次数
- 比例阈值:自己设定的 , 比例阈值=慢调用次数➗调用次数
- 统计时长:时间的判断依据
- 最小请求数:设置的调用最小请求数,上图比如1秒钟打进来10个线程(大于我们配置的5个了)调用被触发
测试:这时我们可以使用浏览器访问搭配Jmeter进行测试访问:http://localhost:8402/testF
②、异常比例策略
这里就是根据异常的比例进行判断是否熔断和慢调用比例策略原理差不多
例如下面的Sentinel配置:
1000ms内请求数大于5个,且一异常比例大于0.1,则进入熔断…
测试:
注意这里要区分一下,报错页面和熔断之后的页面
③、异常数策略
当异常数达到一定的数量的时候进入熔断…
例如下面的Sentinel配置:
1000ms内请求数大于5个,且一异常数大于1个…
@SentinelResource注解
它可以指定 限流返回处理 和 服务降级处理
- 限流返回处理: 是指当被限流(如熔断、流控)
之后返回的值,如Sentinel中默认返回的值为:Blocked by Sentinel (flow limiting)
- 服务降级处理: 当方法抛出 业务异常(非 Sentinel 拦截的异常)时,返回自定义的降级响应。
代码测试
@RestController
public class testSentinelResourceController {@SentinelResource(/*资源名*/value = "testAnn",/*指定限流返回处理的方法名*/blockHandler = "block",/*指定服务降级处理的方法名*/fallback = "testFallback")@GetMapping("/testH/{id}")public String testH(@PathVariable("id") Integer id) {if (id == 0) {throw new RuntimeException("id 不可以为零");}return "我是testH,id = " + id;}/*限流返回处理*/public String block(@PathVariable("id") Integer id, BlockException ex) {return "服务启动失败,已进入熔断,id:" + id;}/*服务降级处理*/public String testFallback(@PathVariable("id") Integer id, Throwable ex) {return "程序异常:" + ex.getMessage();}
}
注意这里的两个方法的异常参数是一定要传的,因为:
① 方法签名匹配的强制性要求
@SentinelResource 的 blockHandler 和 fallback 方法需要严格匹配原方法的参数列表, 并在末尾追加异常参数。 这是 Sentinel 框架的设计约束, 目的是: 明确区分处理逻辑的触发场景(是 Sentinel 规则拦截还是业务异常), 确保框架能正确路由调用到对应的处理方法。②实现动态处理逻辑
通过异常参数,可以基于不同的错误类型动态调整响应内容,
例如:根据流控规则类型返回不同的提示。 针对特定业务异常(如网络超时)执行重试逻辑。
记录详细的异常日志用于监控分析。
4、热点规则
注意:这里的 热点 并不是指的接口,而是 参数
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。
比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
代码演示
@RestController
public class testHotKeyController {@GetMapping("/testHotKey")@SentinelResource(value = "HotKey", blockHandler = "handler")public String testHotKey(@RequestParam(value = "p1", required = false) String p1,/*required:此参数是否必填*/@RequestParam(value = "p2", required = false) String p2) {return "------testHotKey";}public String handler(String p1, String p2, BlockException e) {return "---------服务限流---------";}
}
sentinel配置
测试(多次请求)
- http://localhost:8402/testHotKey?p1=asdf
- http://localhost:8402/testHotKey?p1=chyb
- http://localhost:8402/testHotKey?p2=ajsd
会发现只要有p1都会有限流的情况,但是当p1=chyb时明显就不会了,这是因为我们设置的阀值为500
5、授权规则
根据设定的依据
origin
参数来设置 黑名单和白名单
代码演示:
/*设置黑白名单的参数名*/
@Component
public class MyRequestOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getParameter("serverName");}
}
/*这里不太懂的可以先往下看,后面会有解释*/
/*业务类*/
@RestController
public class EmpowerController {@GetMapping(value = "/empower")public String requestSentinel() {return "Sentinel授权规则";}
}
配置sentinel,添加授权
测试
http://localhost:8402/empower?serverName=test
会直接熔断,这是因为 serverName=test为黑名单
RequestOriginParser部分源码分析
为什么实现RequestOriginParser接口并重写parseOrigin方法就可以对黑白名单的控制?
这里我们查看官网
中的解释:
由此可知ContextUtil.enter(resourceName, origin)
调用这个方法来进行黑白名单的控制的其中调用过程是:
调用过程:
(这里我是直接从准备调用ContextUtil.enter
前开始往上寻找到我们重写的方法MyRequestOriginParser.parseOrigin
)
我们直接看到AbstractSentinelInterceptor
这个拦截器,中的preHandler(请求前)方法中
//...
String origin = this.parseOrigin(request);
String contextName = this.getContextName(request);
ContextUtil.enter(contextName, origin);
//....
这里的
ContextUtil.enter(contextName, origin);
就是我们要找的怎么调用方信息,
这时我们直接向前面找origin,这里就到了String origin = this.parseOrigin(request);
我们在看到这个方法,
//....
origin = this.baseWebMvcConfig.getOriginParser().parseOrigin(request);
//....
return origin;
//....
这个时候我们就知道origin就是调用
RequestOriginParser
接口的parseOrigin()
方法,而我们实现它并对和这个方法进行重写也就相当于间接的对origin进行修改了
(这里大家可以按照这个步骤打debug,按照方法的调用顺序就很清楚了)
6、规则的持久化
前言
在上述的过程中大家应该已经发现了每当重启的时候都要重新进行配置Sentinel,这时就需要持久化配置,但是Sentinel并没有自带持久化功能,需要结合Nacos才可以完成,
所以在这里在从述一下,这里的Sentinel版本要1.8以上,且Spring Cloud Alibaba
、Spring Cloud
、Spring Boot
三者的关系一定不要有依赖冲突
这里可以直接参看官网:https://sca.aliyun.com/docs/2023/overview/version-explain/
代码基本配置
这里可以继续使用上面的代码,但是有部分配置需要进行修改:
- 检查依赖是否有:
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 修改配置文件
server:port: 8402
spring:application:name: cloudAlibaba-sentinelTest-servicecloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口dashboard: localhost:8080 #sentinel的地址web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路datasource:# 测试流控规则的持久化ds1:nacos:server-addr: localhost:8848data-id: ${spring.application.name}group-id: DEFAULT_GROUP# 数量类型data-type: json# 源码地址:com.alibaba.cloud.sentinel.datasource.RuleType# 有五种类型(对呀Sentinel中的规则):# FLOW(流控)、DEGRADE(熔断)、PARAM_FLOW(热点)、SYSTEM(系统保护)、AUTHORITY(授权)rule-type: flow# 测试熔断规则的持久化ds2:nacos:server-addr: localhost:8848data-id: ${spring.application.name}_degradegroup-id: DEFAULT_GROUPdata-type: jsonrule-type: degrade# 测试热点规则的持久化ds3:nacos:server-addr: localhost:8848data-id: ${spring.application.name}_param_flowgroup-id: DEFAULT_GROUPdata-type: jsonrule-type: param_flow# 测试系统规则的持久化ds4:nacos:server-addr: localhost:8848data-id: ${spring.application.name}_systemgroup-id: DEFAULT_GROUPdata-type: jsonrule-type: system# 测试授权规则的持久化ds5:nacos:server-addr: localhost:8848data-id: ${spring.application.name}_authoritygroup-id: DEFAULT_GROUPdata-type: jsonrule-type: authority
- 在nacos中创建配置持久化Sentinel规则
这里就不解释如何创建,直接开始配置,要是不知道的话可以看
《springCloud/Alibaba常用中间件之Nacos服务注册与发现》哪里又说
①:测试流控规则的持久化
创建完nacos配置之后,进行编辑:
配置规则及解释如下:(注意配置中要符合Json格式)
[{/*资源名*/"resource": "/testB",/*针对来源*/"limitApp": "default",/*限流阈值类型(1:QPS; 0:并发线程数)*/"grade": 1,/*单机阀值*/"count": 1,/*流控模式:0:直接; 1:关联; 2:链路*/"strategy": 1,/*流控效果:0:快速失败; 1:Warm Up(预热模式); 2:排队等待*/"controlBehavior": 0,/*关联资源、入口资源(关联、链路模式)*/"refResource": "/testA",/*是否打开集群*/"clusterMode": false/*"strategy": 0, // 流控模式(0:直接; 1:关联; 2:链路)"warmUpPeriodSec": 10, // 预热时间(秒,预热模式需要此参数)*/}
]
sentinel的web界面展示:
②:测试熔断规则的持久化
Nacos的配置:
[{/*资源名*/"resource": "/testF",/*熔断策略,支持慢调用比例(0),异常比例(1),异常数(2)*/"grade": 0,/*统计时长(ms)*/"statIntervalMs": 1000,/*最小请求数*/"minRequestAmount": 10,/*熔断时长*/"timeWindow": 10,/*最大RT*/"count": 1000,/*比例阈值*/"slowRatioThreshold": 0.1
}]
sentinel的web界面展示:
③:测试热点规则的持久化
Nacos配置:
[{/*资源名*/"resource": "HotKey",/*限流模式:QPS(1),可选项只有他,所以这里不设置也可以*/"grade": 1,/*参数索引*/"paramIdx": 0,/*单机阀值*/"count": 1,/*统计窗口时长*/"durationInSec": 1,/*是否开启集群*/"clusterMode": false,/*高级选项配置*/"paramFlowItemList": [{/*参数类型(不写也可以,Nacos会自动判断)*/"classType": "String",/*参数值*/"object": "chyb",/*单机阀值*/"count": 200}]}
]
Setinel的web界面展示:
④:测试系统规则的持久化
Nacos配置:
[{"avgRt": -1, // RT"highestCpuUsage": -1, // CPU 使用率"highestSystemLoad": -1, // LOAD"maxThread": 1, // 线程数"qps": -1, // 入口 QPS"count": 40, // 阈值,在CPU使用率中是百分比}
]
Sentinel的web界面展示
⑥:测试授权规则的持久化
Nacos配置:
[{/*资源名*/"resource": "/empower",/*流控应用*/"limitApp": "test1,test2",/*授权类型:0(白名单),1(黑名单)*/"strategy": 1}
]
Setinel的web界面展示:
7、OpenFeign与Sentinel集成实现fallback服务降级
OpenFeign主要作用就是将微服务要暴漏给客户的API进行统一封装,从而方便管理。
而与Sentinel集成可以完成的一个核心的功能就是统一进行设置 fallback,这时就不需要每设计一个接口就要创建一个 *
fallback* 方法
代码实现演示:
准备代码:创建一个服务并提供一个接口用来测试,还要注册到nacos服务上,在创建一个Model并写Openfeign对外暴漏的API接口(可以前面的springCloud/Alibaba常用中间件——OpenFeign)
修改Openfeign接口,添加注解属性:fallback
/*** value:服务端的服务名* failback:指定服务降级后执行的类*/
@FeignClient(value = "nacos-payment-provider", fallback = PayTwoFeignSentinelApiFallBack.class)
public interface PayFeignSentinelApiTwo {// 对外暴漏的API接口@GetMapping("/pay/nacos/get/{orderNo}")ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo);
}
降级后执行的类代码演示
/*注入容器*/
@Component
/*实现接口,并重写方法作为此即可的服务降级处理*/
public class PayTwoFeignSentinelApiFallBack implements PayFeignSentinelApiTwo {@Overridepublic ResultData getPayByOrderNo(String orderNo) {return ResultData.fail(ReturnCodeEnum.RC201);}
}
编写客户端
- pom依赖导入
<dependencies><!-- 引入自己定义的api通用包 --><dependency><groupId>com.chyb.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>
- 编写配置,并修改启动类
server:port: 83
spring:application:name: nacos-sentinelFeign-order-consumercloud:nacos:discovery:server-addr: localhost:8848
#消费者将要去访问的微服务名称(nacos微服务提供者叫什么你写什么)
service-url:nacos-user-service: http://nacos-payment-provider
# 激活Sentinel对Feign的支持
feign:sentinel:enabled: true
@SpringBootApplication
@EnableDiscoveryClient/*启用服务发现*/
@EnableFeignClients/*启动openFeign*/
public class Main83 {public static void main(String[] args) {SpringApplication.run(Main83.class, args);}
}
- 编写业务类
@RestController
public class testFeignSentinel {@Resourceprivate PayFeignSentinelApiTwo payFeignSentinelApiTwo;@GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo) {return payFeignSentinelApiTwo.getPayByOrderNo(orderNo);}
}
- 测试
启动服务和客户之后,查看暴漏的API接口(若是前面没有错误的话是正常的状态),
然后再将服务端直接关掉,在使用客户端进行请求便会直接到对应的服务降级处理方法哪里
8、GateWay与Sentinel集成实现集体服务限流
概念:GateWay网关是用来对外部请求进行过滤以及管理等操作,结合Sentinel可以更细致化的去控制请求。
注意:Openfeign和GateWay两个与Sentinel的集成别搞混了,如下图所示:
维度 | OpenFeign + Sentinel | Gateway + Sentinel |
---|---|---|
流量类型 | 服务间调用(东西流量) | 外部请求入口(南北流量) |
限流粒度 | 服务级别(如限制调用 user-service) | 全局入口级别(如限制 /api/** 路径) |
防护目标 | 保护调用方(防止下游服务故障拖垮自己) | 保护整个系统(防止外部流量压垮后端服务) |
参数级控制 | 不支持(需自定义代码) | 支持(如按 IP、Header 限流) |
若是还是一脸懵的话就记住:
Openfeign是控制服务之间的调用,解决了服务之间的依赖问题。
而GateWay是控制外部请求的调用,解决入口层的高并发和安全问题。
代码演示:
- pom依赖导入
<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><!--nacos-discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--添加负载均衡的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
</dependencies>
- 修改yml和启动类
server:port: 9530
spring:application:name: cloudalibaba-sentinel-gateway-testcloud:nacos:discovery:server-addr: localhost:8848gateway:routes:- id: pay_routh
# uri: http://localhost:9001 服务网址uri: lb://nacos-payment-provider #使用负载均衡和服务名进行动态访问predicates:- Path=/pay/** #配置Path的过滤
@SpringBootApplication
@EnableDiscoveryClient/*nacos服务注册*/
public class Main9530 {public static void main(String[] args) {SpringApplication.run(Main9530.class, args);}
}
- 创建配置类
@Configuration
public class GatewayConfiguration {/*这段代码是 Spring Cloud Gateway 集成 Sentinel 流量控制的核心配置,主要用于注册 Sentinel 的全局过滤器和自定义的异常处理器,实现网关层面的流量控制(如限流、熔断)及规则触发后的响应处理。直接可以在在官网上复制下来:https://sentinelguard.io/zh-cn/docs/api-gateway-flow-control.html*//*----------作用:流量拦截:通过全局过滤器检查 Sentinel 规则。异常处理:自定义限流、熔断后的响应。响应格式适配:支持 JSON、HTML 等多种格式。-------------------*/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.PostConstructpublic void doInit() {initBlockHandler();}//处理/自定义返回的例外信息。private void initBlockHandler() {Set<GatewayFlowRule> rules = new HashSet<>();/*自定义流控规则*/rules.add(new GatewayFlowRule("pay_routh1")/*设置单机阀值*/.setCount(2)/*设置间隔时间*/.setIntervalSec(1));/*将自定义的流控规则,加载到Sentinel中*/GatewayRuleManager.loadRules(rules);BlockRequestHandler handler = new BlockRequestHandler() {/*** 触发限流后反会的信息** @param exchange 请求的信息列如请求/响应报文等,这里在自定义网关哪里有说* @param t 必须要带的异常参数,类似于fallback中的异常参数* @return*/@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {Map<String, String> map = new HashMap<>();map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("errorMessage", "请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");return ServerResponse/*设置Http响应状态*/.status(HttpStatus.TOO_MANY_REQUESTS)/*指定响应内容类型*/.contentType(MediaType.APPLICATION_JSON)/*响应体,通过BodyInserters.fromValue将map转发为json*/.body(BodyInserters.fromValue(map));}};/*Sentinel的网关回调管理器,用于注册自定义处理器(如限流响应、异常处理等)*/GatewayCallbackManager/*注册到Sentinel,覆盖默认的限流响应行为*/.setBlockHandler(handler);}
}
GatewayFlowRule对象中的字段介绍:参考官方文档
resource
:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。resourceMode
:规则是针对 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)还是用户在 Sentinel 中定义的 API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是 route。grade
:限流指标维度,同限流规则的 grade 字段。count
:限流阈值intervalSec
:统计时间窗口,单位是秒,默认是 1 秒。controlBehavior
:流量整形的控制效果,同限流规则的 controlBehavior 字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。burst
:应对突发请求时额外允许的请求数目。maxQueueingTimeoutMs
:匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。paramItem
:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。其中的字段:parseStrategy
:从请求中提取参数的策略,目前支持提取来源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意 Header(PARAM_PARSE_STRATEGY_HEADER)和任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM)四种模式。fieldName
:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。pattern
:参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。(1.6.2 版本开始支持)matchStrategy
:参数值的匹配策略,目前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2 版本开始支持)
- 测试
直接通过网关端口进行范文服务API多次请求看是否会触发熔断规则,并降级。
上述大部分代码以上传到gitee:https://gitee.com/banhuayue/springCloud-Alibaba-code.git
笔记参考来自尚硅谷
相关文章:

springCloud/Alibaba常用中间件之Setinel实现熔断降级
文章目录 SpringCloud Alibaba:依赖版本补充Sentinel:1、下载-运行:Sentinel(1.8.6)下载sentinel:运行:Sentinel <br> 2、流控规则① 公共的测试代码以及需要使用的测试Jmeter①、流控模式1. 直接:2. 并联:3. 链路: ②、流控效果1. 快速…...
从裸机开发到实时操作系统:FreeRTOS详解与实战指南
从裸机开发到实时操作系统:FreeRTOS详解与实战指南 本文将带你从零开始,深入理解嵌入式系统中的裸机开发与实时操作系统,以FreeRTOS为例,全面剖析其核心概念、工作原理及应用场景。无论你是嵌入式新手还是希望提升技能的开发者&am…...

Deeper and Wider Siamese Networks for Real-Time Visual Tracking
现象: the backbone networks used in Siamese trackers are relatively shallow, such as AlexNet , which does not fully take advantage of the capability of modern deep neural networks. direct replacement of backbones with existing powerful archite…...
简单介绍C++中线性代数运算库Eigen
Eigen 是一个高性能的 C 模板库,专注于线性代数、矩阵和向量运算,广泛应用于科学计算、机器学习和计算机视觉等领域。以下是对 Eigen 库的详细介绍: 1. 概述 核心功能:支持矩阵、向量运算,包括基本算术、矩阵分解&…...
Python爬虫实战:研究decrypt()方法解密
1. 引言 1.1 研究背景与意义 在当今数字化时代,网络数据蕴含着巨大的价值。然而,许多网站为了保护其数据安全和商业利益,会采用各种加密手段对传输的数据进行处理。这些加密措施给数据采集工作带来了巨大挑战。网络爬虫逆向解密技术应运而生,它通过分析和破解网站的加密机…...

黑马程序员C++2024版笔记 第0章 C++入门
1.C代码的基础结构 以hello_world代码为例: 预处理指令 #include<iostream> using namespace std; 代码前2行是预处理指令,即代码编译前的准备工作。(编译是将源代码转化为可执行程序.exe文件的过程) 主函数 主函数是…...
c#定义占用固定字节长度的结构体字段
在c中,经常类似这样定义结构体: struct DEMO_STRUCT {int a;int b;char c[128]; }; 定义这个结构体,占用了136个字节的内存空间,关键的是,它的内存块是连续的,其中c占用了128个字节 然后如果想在c#中定义…...

foxmail - foxmail 启用超大附件提示密码与帐号不匹配
foxmail 启用超大附件提示密码与帐号不匹配 问题描述 在 foxmail 客户端中,启用超大附件功能,输入了正确的账号(邮箱)与密码,但是提示密码与帐号不匹配 处理策略 找到 foxmail 客户端目录/Global 目录下的 domain.i…...

Crowdfund Insider聚焦:CertiK联创顾荣辉解析Web3.0创新与安全平衡之术
近日,权威金融科技媒体Crowdfund Insider发布报道,聚焦CertiK联合创始人兼CEO顾荣辉教授在Unchained Summit的主题演讲。报道指出,顾教授的观点揭示了Web3.0生态当前面临的挑战,以及合规与技术在推动行业可持续发展中的关键作用。…...
EDR与XDR如何选择适合您的网络安全解决方案
1. 什么是EDR? 端点检测与响应(EDR) 专注于保护端点设备(如电脑、服务器、移动设备)。通过在端点安装代理软件,EDR实时监控设备活动,检测威胁并快速响应。 EDR核心功能 实时监控:…...

PowerBI链接EXCEL实现自动化报表
PowerBI链接EXCEL实现自动化报表 曾经我将工作中一天的工作缩短至2个小时,其中最关键的一步就是使用PowerBI链接Excel做成一个自动化报表,PowerBI更新源数据,Excel更新报表并且保留报表格式。 以制作一个超市销售报表为例,简单叙…...

腾讯云MCP数据智能处理:简化数据探索与分析的全流程指南
引言 在当今数据驱动的商业环境中,企业面临着海量数据处理和分析的挑战。腾讯云MCP(Managed Cloud Platform)提供的数据智能处理解决方案,为数据科学家和分析师提供了强大的工具集,能够显著简化数据探索、分析流程,并增强数据科学…...

Android framework 中间件开发(一)
在Android开发中,经常会调用到一些系统服务,这些系统服务简化了上层应用的开发,这便是中间件的作用,中间件是介于系统和应用之间的桥梁,将复杂的底层逻辑进行一层封装,供上层APP直接调用,或者将一些APP没有权限一些操作放到中间件里面来实施. 假设一个需求,通过中间件调节系统亮…...
Lua中使用module时踩过的坑
在lua中设置某个全局对象(假如对象名为LDataUser)为nil时, LDataUser并不会变成nil, 但在有些情况下设置LDataUser nil时却真变成了nil,然后会导致后续再使用LDataUser时会抛nil异常, 后来发现是使用module搞的鬼,下面看看豆包AI给的解释,还…...

MATLAB中的概率分布生成:从理论到实践
MATLAB中的概率分布生成:从理论到实践 引言 MATLAB作为一款强大的科学计算软件,在统计分析、数据模拟和概率建模方面提供了丰富的功能。本文将介绍如何使用MATLAB生成各种常见的概率分布,包括均匀分布、正态分布、泊松分布等,并…...

C# 面向对象 构造函数带参无参细节解析
继承类构造时会先调用基类构造函数,不显式调用基类构造函数时,默认调用基类无参构造函数,但如果基类没有写无参构造函数,会无法调用从而报错;此时,要么显式的调用基类构造函数,并按其格式带上参…...
轨迹误差评估完整流程总结(使用 evo 工具)
roslaunch .launch rosbag play your_dataset.bag -r 2.0 ✅ 第二步:录制估计轨迹 bash 复制编辑 rosbag record -O traj_only.bag /aft_mapped_to_init 运行一段时间后 CtrlC 停止,生成 traj_only.bag 第三步:提取估计轨迹和真值轨迹为…...
Spring Boot 跨域问题全解:原理、解决方案与最佳实践
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、跨域问题的本质 1.1 什么是跨域? 跨域(Cross-Origin)问题源于浏览器的同源策略(Same-Origin Policy&…...
vhca_id 简介,以及同 pf, vf 的关系
vhca_id 指的是 Virtual Host Channel Adapter ID(虚拟主机通道适配器编号),它是 NVIDIA(Mellanox)网络设备虚拟化架构中的一个核心概念。 它与 PF(物理功能)、VF(虚拟功能ÿ…...
LlamaIndex 第九篇 Indexing索引
索引概述 数据加载完成后,您将获得一个文档对象(Document)列表(或节点(Node)列表)。接下来需要为这些对象构建索引(Index),以便开始执行查询。 索引(Index) 是一种数据结构,能够让我们快速检索…...
微信小程序原生swiper高度自适应图片,不同屏幕适配,正方形1:1等比例图片轮播
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 ✨一、前言分析 一开始只设了图片的mode="widthFix" st…...

在 C# 中将 DataGridView 数据导出为 CSV
在此代码示例中,我们将学习如何使用 C# 代码将 DataGridView 数据导出到 CSV 文件并将其保存在文件夹中。 在这个程序中,首先,我们必须连接到数据库并从中获取数据。然后,我们将在数据网格视图中显示该数据,…...
解锁 CPU 性能天花板:多维优化策略深度剖析
在数字世界的底层战场,CPU 如同指挥千军万马的将军,掌控着程序运行的节奏与效率。无论是大型服务器应用,还是手机端的轻量化程序,CPU 性能的优化都如同解锁隐藏力量的密码,能让程序在执行效率上实现质的飞跃。本文将深…...
Android SwitchButton 使用详解:一个实际项目的完美实践
Android SwitchButton 使用详解:一个实际项目的完美实践 引言 在最近开发的 Android 项目中,我遇到了一个需要自定义样式开关控件的需求。经过多方比较,最终选择了功能强大且高度可定制的 SwitchButton 控件。本文将基于实际项目中的使用案…...
Kafka如何实现高性能
Kafka如何实现高性能 Kafka之所以能成为高性能消息系统的标杆,是通过多层次的架构设计和优化实现的。 一、存储层优化 1. 顺序I/O设计 日志结构存储:所有消息追加写入,避免磁盘随机写分段日志:将日志分为多个Segment文件&…...

MySQL中表的增删改查(CRUD)
一.在表中增加数据(Create) INSERT [INTO] TB_NAME [(COLUMN1,COLUMN2,...)] VALUES (value_list1),(value_list2),...;into可以省略可仅选择部分列选择插入,column即选择的列, 如图例可以选择仅在valuelist中插入age和id如果不指…...

项目思维vs产品思维
大家好,我是大明同学。 这期内容,我们来聊一下项目思维和产品思维的区别。 项目是实施关键,力求每一步都精准到位;产品则是战略导向,确保所选之路正确无误。若缺乏优异成果,即便按时完成,也只…...

游戏引擎学习第285天:“Traversables 的事务性占用”
回顾并为当天的工作做准备 我们有一个关于玩家移动的概念,玩家可以在点之间移动,而且当这些点移动时,玩家会随之移动。现在这个部分基本上已经在工作了。我们本来想实现的一个功能是:当玩家移动到某个点时,这个点能“…...
基于DWT的音频水印算法
基于离散小波变换(DWT)的音频水印算法是一种结合信号处理与信息隐藏的技术,旨在将版权信息或标识隐蔽地嵌入音频信号中,同时保证不可感知性和鲁棒性。以下是该算法的核心步骤及关键技术点: 1. 算法基本原理 DWT…...
小刚说C语言刷题—1700请输出所有的2位数中,含有数字2的整数
1.题目描述 请输出所有的 2 位数中,含有数字 2 的整数有哪些,每行 1个,按照由小到大输出。 比如: 12、20、21、22、23… 都是含有数字 2的整数。 输入 无 输出 按题意要求由小到大输出符合条件的整数,每行 1 个。…...