03-13、SpringCloud Alibaba第十三章,升级篇,服务降级、熔断和限流Sentinel
SpringCloud Alibaba第十三章,升级篇,服务降级、熔断和限流Sentinel
一、Sentinel概述
1、Sentinel是什么
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。一句话概括:sentinel即Hystrix的替代品官网: https://sentinelguard.io/zh-cn/下载:https://github.com/alibaba/Sentinel/releases
2、Sentinel基本概念
2.1、资源:
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调
用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,
URL,甚至服务名称作为资源名来标示资源。
2.2、规则:
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
2.3、流量控制:
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度
上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能
力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状.流量控制有一下几个角度:
1、资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
2、运行指标,例如 QPS、线程池、系统负载等;
3、控制的效果,例如直接限流、冷启动、排队等。
2.4、熔断降级:
降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳
定,最终会导致请求发生堆积。这个问题和 Hystrix 里面描述的问题是一样的。Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的
时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。Sentinel和Hystrix在限制手段上,采取了不一样的方法:1、Hystrix通过线程池的方式:
Hystrix 通过线程池的方式,来对依赖进行了隔离。2、Sentinel 对这个问题采取了两种手段:
a、通过并发线程数进行限制
b、通过响应时间对资源进行降级
2.5、系统负载保护:
Sentinel 同时对系统的维度提供保护。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求
进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。
如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之
内处理最多的请求。
二、Sentinel控制台安装
Sentinel分为两个部分:
1、核心库
2、控制台dashboard,基于Springboot开发,打包后可直接运行,不需要Tomcat等额外的容器
下载:
https://github.com/alibaba/Sentinel/releases
运行:
Sentinel Dashboard默认的端口是8080java -jar sentinel-dashboard-1.7.0.jar
访问:
http://localhost:8080/账号:sentinel 密码:sentinel
三、Sentinel案例
3.1、初始化演示工程
创建cloudalibaba-sentinel-service-8401
<parent><artifactId>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-sentinel-service-8401</artifactId>
POM
<?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>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-sentinel-service-8401</artifactId><dependencies><!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency><!--SpringCloud ailibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--SpringCloud ailibaba nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.lee.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- SpringBoot整合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><!--日常通用jar包配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.6.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>
application.yml
server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8080port: 8719 #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口management:endpoints:web:exposure:include: '*'
主启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelMain8401 {public static void main(String[] args) {SpringApplication.run(SentinelMain8401.class,args);}
}
业务类:
@Slf4j
@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA(){return "=======>testA";}@GetMapping("/testB")public String testB(){return "=======>testB";}
}
测试:
1、启动nacos server、Sentinel-Dashboard、CloudAlibaba-sentinel-service-8401
2、查看sentinel控制台 http://localhost:8080/结果:空空如也
(因为:Sentinel采用的是懒加载模式)
3、浏览:http://localhost:8401/testA和http://localhost:8401/testB
4、再查看sentinel控制台 http://localhost:8080/
3.2、流控规则
资源新增流控,可以通过两个地方来添加:
1、簇点链路-点击”+流控“
2、流控规则-点击"新增流控规则"阈值类型:
QPS:系统每秒钟处理完成的请求次数(QPS是在请求进入应用之前就处理,线程数是在请求进入应用之后处理)
3.2.1、流控模式
流控3种模式分为:直接、关联、链路
3.2.1.1、直接
测试:
1、直接的配置如上
2、每秒访问一次http://localhost:8401/testA正常
3、每秒多次快速的访问http://localhost:8401/testABlocked by Sentinel (flow limiting)
(当再次恢复每秒1次的访问频率时,又可正常访问)思考:
访问频次不符合配置规则后直接显示sentinel的默认处理Blocked by Sentinel,我们如何自定义规则不匹配的情况呢?
(后续会介绍:@SentinelResource去做方法的兜底处理,类似Hystrix的@HystrixCommand)
3.2.1.2、关联
什么是关联?即当与testA相关的资源testB达到阈值时,就挂testA
测试:
1、配置规则如上
2、postman模拟并发密集的访问http://localhost:8401/testB
3、浏览器访问http://localhost:8401/testA结果:Blocked by Sentinel (flow limiting)(当对testB密集访问停止后,testA访问恢复正常)
3.2.1.3、链路
新增代码:service
@Slf4j
@Service
public class FlowLimitService {@SentinelResource("findOrder")public String findOrder(){log.info("----order----");return "order";}
}
controller
@Slf4j
@RestController
public class FlowLimitController {@Resourceprivate FlowLimitService flowLimitService;@GetMapping("/testA")public String testA(){flowLimitService.findOrder();return "=======>testA";}@GetMapping("/testB")public String testB(){flowLimitService.findOrder();return "=======>testB";}
}
配置规则:
1、配置规则如上
2、快速访问http://localhost:8401/testA
结果:
###############################有待确认#############
快速访问http://localhost:8401/testB
结果:
###############################有待确认#############
3.2.2、流控效果
3.2.2.1、快速失败
源码:
com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController上面写流控模式的时候已经展示了效果,不符合配置的时候,快速做出对应的反映,如
3.2.2.2、Warn Up预热
源码:
com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController公式:
阈值除以coldFactor(默认为3),经过预热时长后才会达到阈值限流-冷启动:
当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲
的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启
动,预热)模式就是为了实现这个目的的。应用场景:
秒杀系统在开启的瞬间,会有很多流量上来,会把系统打死,预热方式就是为了保护系统,可以慢慢的把流量放进来。
慢慢的把阈值增长到设定的阈值、
配置解读:
系统初始化的阈值为10/3约等于3,即阈值刚开始为3.然后过了5秒后阈值才逐渐升到10
3.2.2.3、排队等待
源码:
com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController匀速排队,阈值必须设置为QPS。匀速排队会严格控制请求通过的时间间隔。也即是让请求以均匀的速度通过,对应的是漏桶算法。(类似消息队列)
配置解读:
/testB每秒1次请求,超过的话就排队等待。等待的超时时间是20000ms
3.3、降级规则
降级规则包括:RT、异常比例、异常数
3.3.1、RT平均响应时间
RT平均响应时间:
当1s内持续进入5个请求,对应时刻的平均响应时间均超过阈值,那么在接下的时间窗口之内,对这个方法的调用都会自动地
熔断(抛出DegradeException).Sentinel的默认RT上限是4900ms,超出此阈值的都会算作4900ms。若需要变更此上线可以通过:
-Dcsp.sentinel.statistic.max.rt=xxx来配置
新增代码:
@GetMapping("/testD")
public String testD()
{try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}log.info("testD 测试RT");return "=======>testD";
}
配置
测试:
如上JMeter创建1s中10个线程的访问去请求testD.然后再浏览器上访问http://localhost:8401/testD
结果:
Blocked by Sentinel (flow limiting)(配置中,我们希望200毫秒处理完这次任务,如果200毫秒还没处理完,在未来1s的时间窗口内,断路器打开,微服务不可用)(当我们停止JMeter测试后,没这么大访问量了,断路器关闭,微服务恢复。)
3.3.2、异常比例
异常比例:
当资源的每秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下来的时间窗口之
内,对这个方法的调用都会自动返回。
新增代码:
@GetMapping("/testE")
public String testE()
{log.info("testE 测试RT");int age = 10/0;return "------testE";
}
配置规则:
测试:
JMeter压测testE,每秒10个线程浏览器访问:http://localhost:8401/testE结果:不是报错,而是Blocked by Sentinel (flow limiting)结论:
开启JMeter后,直接高并发发送请求,多次调用达到了我们的配置条件。断路器开启,微服务不可用,不再报错error而是
进入服务降级
3.3.3、异常数
异常数:
当资源近1分钟的异常数目超过阈值之后进入熔断,这个统计时间窗口是分钟级别的,若timewindow小于60s,则结束熔断状
态后仍可能再次进入熔断状态
新增代码:
@GetMapping("/testF")
public String testF()
{log.info("testF 测试异常数");int age = 10/0;return "------testF 测试异常数";
}
配置规则如下:
浏览器访问:http://localhost:8401/testF
前5次报错,走Error
之后报:Blocked by Sentinel (flow limiting)
61s后,服务熔断解除,走Error
3.4、热点KEY限流
3.4.1、普通配置
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限
制。
之前的case,限流出现问题后,都是Sentinel的默认提示:Blocked by Sentinel (flow limiting)
我们将使用@SentinelResource,类似Hystrix的@HystrixCommand。当方法出现问题后就找对应的兜底方法返回。
新增方法如下:
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,@RequestParam(value = "p2",required = false) String p2) {//int age = 10/0;return "------testHotKey";
}//兜底方法
public String deal_testHotKey (String p1, String p2, BlockException exception){return "------deal_testHotKey,o(╥﹏╥)o";
}
配置规则如下:
测试:
快速访问:http://localhost:8401/testHotKey 结果:------testHotKey快速访问:http://localhost:8401/testHotKey?p1=abc 结果:------deal_testHotKey,o(╥﹏╥)o快速访问:http://localhost:8401/testHotKey?p2=123 结果:------testHotKey快速访问:http://localhost:8401/testHotKey?p1=abc&p2=123 结果:------deal_testHotKey,o(╥﹏╥)o如果不快速访问,达不到阈值时,也只会返回------testHotKey
3.4.2、参数例外:
我们有时候期望当P1参数为某个特殊值时,它的限流值和平时不一样,假如当P1==5时,期望它的阈值为200。
测试:
1、浏览器快速访问:http://localhost:8401/testHotKey?p1=5 返回:------testHotKey2、浏览器快速访问:http://localhost:8401/testHotKey?p1=3 返回:------deal_testHotKey,o(╥﹏╥)o注意:参数必须是基础数据类型
3.5、系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等
几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量
(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。系统规则支持以下的模式:
1、load自适应:仅对 Linux/Unix-like 机器生效
系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估
算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是
CPU cores * 2.5。2、CPU usage:
当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。3、平均 RT:
当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。4、并发线程数:
当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。5、入口 QPS:
当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
3.6、@SentinelResource
@SentinelResource:类似Hystrix的@HystrixCommand,做兜底服务自定义其中blockXXXX是处理:配置违规的@blockHandlerClass 处理类@blockHandler 处理类下的处理方法fallback:处理异常,做服务降级的
exceptionToIgnore:忽略异常【程序异常和违规同时发生优先执行blockHandler】
3.6.1、按资源名称限流
新增业务类RateLimitController:
@Slf4j
@RestController
public class RateLimitController {@GetMapping("/byResource")@SentinelResource(value = "byResource",blockHandler = "handleException")public CommonResult byResource(){return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));}public CommonResult handleException(BlockException exception){return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");}}
新增配置:
测试:
上述配置解析:
表示1秒钟内查询次数大于1,就限流跑到我们自定义的方法1、1s访问一次:http://localhost:8401/byResource
结果:{"code":200,"message":"按资源名称限流测试OK","data":{"id":2020,"serial":"serial001"}}2、1s内快速多次访问:http://localhost:8401/byResource
结果:{"code":444,"message":"com.alibaba.csp.sentinel.slots.block.flow.FlowException\t 服务不可用","data":null}根据资源名称限流,会优先返回我们自定义的处理信息,没有自定义的返回Sentinel默认限流处理信息
3.6.2、按URL地址限流
新增方法:
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl",blockHandler = "byUrlHandler")
public CommonResult byUrl()
{return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}public CommonResult byUrlHandler(BlockException exception){return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
新增配置:
测试:
1、1s访问一次:http://localhost:8401/rateLimit/byUrl
结果:
{"code":200,"message":"按url限流测试OK","data":{"id":2020,"serial":"serial002"}}2、1s内快速访问:http://localhost:8401/rateLimit/byUrl
结果:
Blocked by Sentinel (flow limiting)根据url地址限流返回的是Sentinel自带的默认限流处理信息
3.6.3、优化
以上一个方法新增一个对应的处理限流方法,代码冗余且和业务混杂,我们可以将处理方法提出来做单独处理
新增一个handler:
public class CustomerBlockHandler {//注意---这里必须是static且不能为privatepublic static CommonResult handlerException(BlockException exception){return new CommonResult(4444,"按客戶自定义,global handlerException----1");}public static CommonResult handlerException2(BlockException exception){return new CommonResult(4444,"按客戶自定义,global handlerException----2");}}
业务类新增方法:
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException")
public CommonResult customerBlockHandler()
{return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
新增对应的配置,然后测试:
1s内多次快速的访问:http://localhost:8401/rateLimit/customerBlockHandler结果:
{"code":4444,"message":"按客戶自定义,global handlerException----1","data":null}
3.7、Sentinel与Ribbon和Feign的整合
3.7.1、Sentinel与Ribbon
3.7.1.1、创建cloudalibaba-provider-payment-9004和9005
<parent><artifactId>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment-9004</artifactId>
pom
<?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>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-provider-payment-9004</artifactId><dependencies><!--SpringCloud ailibaba nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><groupId>com.lee.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!-- SpringBoot整合Web组件 --><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><!--日常通用jar包配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
</project>
application.yml
server:port: 9004spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址management:endpoints:web:exposure:include: '*'
主启动类
@SpringBootApplication
@EnableDiscoveryClient//服务发现
public class PaymentMain9004 {public static void main(String[] args) {SpringApplication.run(PaymentMain9004.class,args);}
}
业务类
@Slf4j
@RestController
public class PaymentController {@Value("${server.port}")private String serverPort;public static HashMap<Long, Payment> hashMap = new HashMap<>();static{hashMap.put(1L,new Payment(1L,"aaa"));hashMap.put(2L,new Payment(2L,"bbb"));hashMap.put(3L,new Payment(3L,"ccc"));}@GetMapping(value = "/paymentSQL/{id}")public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){Payment payment = hashMap.get(id);CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment);return result;}}
3.7.1.2、创建cloudalibaba-consumer-order-84
<parent><artifactId>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-consumer-order-84</artifactId>
POM
<?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>cloud_2020</artifactId><groupId>com.lee.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloudalibaba-consumer-order-84</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><dependency><groupId>com.lee.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><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.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>
application.yml
server:port: 84spring:application:name: nacos-order-consumercloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8080port: 8719service-url:nacos-user-service: http://nacos-payment-provider
主启动类
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerOrderNacos84 {public static void main(String[] args) {SpringApplication.run(ConsumerOrderNacos84.class,args);}
}
配置类
@Configuration
public class ApplicationContextConfig {@Bean@LoadBalancedpublic RestTemplate getRestTemplate(){return new RestTemplate();}}
业务类
@Slf4j
@RestController
public class CircleBreakerController {public static final String SERVICE_URL = "http://nacos-payment-provider";@Resourceprivate RestTemplate restTemplate;@RequestMapping("/consumer/fallback/{id}")@SentinelResource(value = "fallback") //没有配置//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规//@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler="blockHandler",exceptionsToIgnore = {IllegalArgumentException.class})public CommonResult<Payment> fallback(@PathVariable Long id) {CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);if (id == 4) {throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");}else if (result.getData() == null) {throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");}return result;}//fallbackpublic CommonResult handlerFallback(@PathVariable Long id,Throwable e) {Payment payment = new Payment(id,"null");return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);}//blockHandlerpublic CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {Payment payment = new Payment(id,"null");return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);}}
3.7.1.3、测试:
1、启动nacos-server、sentinel-server、cloudalibaba-provider-payment-9004、9005、
cloudalibaba-consumer-order-84#############测试一############
2、浏览器访问:http://localhost:84/consumer/fallback/1结果:
{"code":200,"message":"from mysql,serverPort: 9004","data":{"id":1,"serial":"aaa"}}
{"code":200,"message":"from mysql,serverPort: 9005","data":{"id":1,"serial":"aaa"}}
两个结果来回切换3、浏览器访问:http://localhost:84/consumer/fallback/4结果:
Whitelabel Error Page#############测试二##############
4、consumer-84业务类放开注解@SentinelResource(value = "fallback",fallback = "handlerFallback")//fallback只负责业务异常5、浏览器访问:http://localhost:84/consumer/fallback/4结果:
{"code":444,"message":"兜底异常handlerFallback,exception内容 IllegalArgumentException,非法参数异常....","data":{"id":4,"serial":"null"}}##############测试三############
6、consumer-84业务类放开注解@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规7、且sentinel控制台新增fallback的降级策略新增降级:资源名:fallback 策略:异常数 异常数:2 时间窗口:28、浏览器访问:http://localhost:84/consumer/fallback/2结果:正常浏览器访问:http://localhost:84/consumer/fallback/4结果:Whitelabel Error Page快速多次访问:http://localhost:84/consumer/fallback/4结果:{"code":445,"message":"blockHandler-sentinel限流,无此流水: blockException null","data":{"id":4,"serial":"null"}}##################测试四############
9、consumer-84业务类放开注解@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler",exceptionsToIgnore = {IllegalArgumentException.class})10、浏览器访问:http://localhost:84/consumer/fallback/4结果:Whitelabel Error Page浏览器访问:http://localhost:84/consumer/fallback/5结果:{"code":444,"message":"兜底异常handlerFallback,exception内容 NullPointerException,该ID没有对应记录,空指针异常","data":{"id":5,"serial":"null"}}结论:@blockHandlerClass 处理类
@blockHandler 处理类下的处理方法
fallback:处理异常,做服务降级的
exceptionToIgnore:忽略异常
3.7.2、Sentinel与OpenFeign
修改module:cloudalibaba-consumer-order-84
POM新增(上面创建的时候就已增加过了)
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
yml新增:
#对Feign的支持
feign:sentinel:enabled: true
新增feign对应的接口:paymentService
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {@GetMapping(value = "/paymentSQL/{id}")public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);}
新增feign接口的对应的服务降级类:PaymentFallbackService
@Component
public class PaymentFallbackService implements PaymentService
{@Overridepublic CommonResult<Payment> paymentSQL(Long id){return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",new Payment(id,"errorSerial"));}
}
新增controller:OrderController
@Slf4j
@RestController
public class OrderController {// OpenFeign@Resourceprivate PaymentService paymentService;@GetMapping(value = "/consumer/feign/paymentSQL/{id}")public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {return paymentService.paymentSQL(id);}}
主启动类新增注解:
@EnableFeignClients
测试:
1、启动nacos-server、sentinel-server、cloudalibaba-provider-payment-9004、9005、
cloudalibaba-consumer-order-842、浏览器访问:http://localhost:84/consumer/feign/paymentSQL/5结果:
{"code":200,"message":"from mysql,serverPort: 9005","data":null}4、此时关闭cloudalibaba-provider-payment-9004、9005两个微服务,重新访问结果:
{"code":44444,"message":"服务降级返回,---PaymentFallbackService","data":{"id":5,"serial":"errorSerial"}}
3.8、Sentinel规则持久化
//TODO 以后再单独列出文章来写
相关文章:

03-13、SpringCloud Alibaba第十三章,升级篇,服务降级、熔断和限流Sentinel
SpringCloud Alibaba第十三章,升级篇,服务降级、熔断和限流Sentinel 一、Sentinel概述 1、Sentinel是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保…...

【k8s 深入学习之 event 聚合】event count累记聚合(采用 Patch),Message 聚合形成聚合 event(采用Create)
参考 15.深入k8s:Event事件处理及其源码分析 - luozhiyun - 博客园event 模块总览 EventRecorder:是事件生成者,k8s组件通过调用它的方法来生成事件;EventBroadcaster:事件广播器,负责消费EventRecorder产生的事件,然后分发给broadcasterWatcher;broadcasterWatcher:用…...

leetcode104.二叉树的最大深度
给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3示例 2: 输入:root [1,null,2] 输出…...

蓝桥杯2117砍竹子(简单易懂 包看包会版)
问题描述 这天, 小明在砍竹子, 他面前有 n 棵竹子排成一排, 一开始第 i 棵竹子的 高度为 hi. 他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 H, 那么 用一次魔法可以 把这一段竹子的高度都变为 ⌊H2⌋…...

LCD与lvgl
LCD与lvgl 目录 LCD与lvgl 回顾 LCD 的驱动层讲解 1、LCD 的常见接口 2、我们的 LCD 的参数 3、LCD 的设备树说明 4、LCD 的设备树说明 5、如何移植 LCD 的驱动(重点) LCD 的应用层开发 1:LCD 应用开发->界面开发的方法 2:LVGL 模拟器安装 3:LVGL 工程创建和…...

SpringBoot 赋能:精铸超稳会员制医疗预约系统,夯实就医数据根基
1绪论 1.1开发背景 传统的管理方式都在使用手工记录的方式进行记录,这种方式耗时,而且对于信息量比较大的情况想要快速查找某一信息非常慢,对于会员制医疗预约服务信息的统计获取比较繁琐,随着网络技术的发展,采用电脑…...

android studio 读写文件操作(应用场景二)
android studio版本:2023.3.1 patch2 例程:readtextviewIDsaveandread 本例程是个过渡例程,如果单是实现下图的目的有更简单的方法,但这个方法是下一步工作的基础,所以一定要做。 例程功能:将两个textvi…...

小尺寸低功耗蓝牙模块在光伏清扫机器人上的应用
一、引言 随着可再生能源的迅速发展,光伏发电系统的清洁与维护变得越来越重要。光伏清扫机器人通过自动化技术提高了清洁效率,而蓝牙模组的集成为这些设备提供了更为智能的管理和控制方案。 二、蓝牙模组的功能与实现: 蓝牙模组ANS-BT103M…...

防火墙有什么作用
防火墙的作用:1. 提供网络安全防护;2. 实施访问控制和流量过滤;3. 检测和阻止恶意攻击;4. 保护内部网络免受未经授权的访问;5. 监控网络流量和安全事件;6. 支持虚拟专用网络(VPN)。防…...

MongoDB-BSON 协议与类型
前言: MongoDB 是一个高性能、无模式的 NoSQL 数据库,广泛应用于大数据处理和实时数据存储。作为一个数据库系统,MongoDB 的核心之一就是其使用的 BSON(Binary JSON)格式,它用于存储数据以及在客户端和数据…...

学习threejs,使用VideoTexture实现视频Video更新纹理
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️VideoTexture 视频纹理 二、…...

怎么获取键值对的键的数值?
问: 通过paelData.cardMap.C0002112可以获取到Cooo2112里面的数据,但是有时候接口返回的不是C0002112而是C0002093或者其他值,请问我该怎么写? 后端返回的数据是这样的: cardMap: { C0002112: { name: Item 1, va…...

数据结构排序算法详解
数据结构排序算法详解 1、冒泡排序(Bubble Sort)2、选择排序(Selection Sort)2、插入排序(Insertion Sort) 1、冒泡排序(Bubble Sort) 原理:越小的元素会慢慢“浮”到数…...

在Linux设置postgresql开机自启动,创建一个文件 postgresql-15.service
在Linux设置postgresql开机自启动,创建一个文件 postgresql-15.service 在Linux设置postgresql开机自启动,创建一个文件 postgresql-15.service1. 创建 systemd 服务文件2. 编辑服务文件3. 保存并退出4. 重新加载 systemd 配置5. 启动 PostgreSQL 服务6.…...

【kafka】消息队列的认识,Kafka与RabbitMQ的简单对比
什么是消息队列? 消息队列(Message Queue,简称 MQ)是一个在不同应用程序、系统或服务之间传递数据的机制。 它允许系统间异步地交换信息,而无需直接交互,确保消息的可靠传输。 想象一下,你正在…...

ProjectSend 身份认证绕过漏洞复现(CVE-2024-11680)
0x01 产品描述: ProjectSend 是一个开源文件共享网络应用程序,旨在促进服务器管理员和客户端之间的安全、私密文件传输。它是一款相当流行的应用程序,被更喜欢自托管解决方案而不是 Google Drive 和 Dropbox 等第三方服务的组织使用。0x02 漏洞描述: ProjectSend r1720 之前…...

Android笔记(三十四):onCreate执行Handler.post在onResume后才能执行?
背景 偶然发现一个点,就是在onCreate执行Handler.post在onResume后才执行,以下是测试代码 多次运行的结果一致,为什么execute runnable不是在onCreate和onResume之间执行的呢,带着疑问撸了一遍Activity启动流程 关键源码分析 …...

关闭模组的IP过滤功能
关闭模组的IP过滤功能 关闭模组的IP过滤功能 本脚本用于关闭模组的IP过滤功能,关闭后, 源地址不是终端IP的数据包,也可以被模组转发给网络 关闭模组的IP过滤功能 cat > /usr/bin/ipfilter << "EOF"echo -e "ATCFUN…...

算法分析与设计复习笔记
插入排序 1. void insert_sort(int A[ ],int n) 2. { 3. int a,i,j; 4. for (i1;i<n;i) { 5. a A[ i ]; 6. j i – 1; 7. while (j>0 && A[j]>a) { 8. A[ j…...

vue-amap 高德地图
vue-amap是一套基于Vue 2/vue3和高德地图的地图组件 vue-amap 高德地图2.0版本的对应vue3...

Numpy基础练习
import numpy as np 1.创建一个长度为10的一维全为0的ndarray对象,然后让第5个元素等于1 n np.zeros(10,dtypenp.int32) n[4] 12.创建一个元素从10到49的ndarray对象 n np.arrange(10,50)3.将第2题的所有元素位置反转 n[::-1]使用np.random.random创建一个10*10的ndarray对象…...

一番赏小程序定制开发,打造全新抽赏体验平台
随着盲盒的热潮来袭,作为传统的潮玩方式一番赏也再次受到了大家的关注,市场热度不断上升! 一番赏能够让玩家百分百中奖,商品种类丰富、收藏价值高,拥有各种IP,从而吸引着各个圈子的粉丝玩家,用…...

【前端】将vue的方法挂载到window上供全局使用,也方便跟原生js做交互
【前端】将vue的方法挂载到window上供全局使用,也方便跟原生js做交互 <template><div><el-button click"start">调用方法</el-button></div> </template> <script> // import { JScallbackProc } from ./JScal…...

Oracle查询优化:高效实现仅查询前10条记录的方法与实践
在 Oracle 中,实现仅查询前10条记录的四种方法 1. 使用 ROWNUM 查询 ROWNUM 是 Oracle 中的伪列,用于限制返回的行数。 SELECT * FROM table_name WHERE condition AND ROWNUM < 10;condition:查询条件。ROWNUM < 10:限制…...

go语言编译问题
go编译 goproxy地址 阿里云 https://mirrors.aliyun.com/goproxy/七牛云 https://goproxy.cn/开源版 https://goproxy.io/nexus社区 https://gonexus.dev/启用 Go Modules 功能 go env -w GO111MODULEon配置 GOPROXY 环境变量,以下三选一 七牛 CDN go env -w …...

mobi文件转成pdf
将 MOBI 文件转换为 PDF 格式通常涉及两个步骤: 解析 MOBI 文件:需要提取 MOBI 文件的内容(文本、图片等)。将提取的内容转换为 PDF:将 MOBI 文件的内容渲染到 PDF 格式。 可用工具 kindleunpack 或 mobi࿱…...

MobaXterm解决中文显示乱码问题
1 问题 打开MobaXterm时,会显示中文乱码。 2 解决方法 右键点击会话,在弹出菜单中选择“编辑会话”,如下: 选择终端字体设置,如下: 字符集换成ISO-8859-1,如下: 网上有说用…...

西门子 SINAMICS G120 变频器借助 ProfiNet 转 EtherCAT 实现与汇川 H5U 通讯实例
一. 案例背景 随着智能制造理念的推进,设备之间的协同工作变得越来越重要。例如,在机器人自动化焊接生产线中,电机驱动的焊接机器人需要与其他设备协同工作,这就要求负责电机控制的变频器和控制整个生产线流程的PLC能…...

流媒体之linux下离线部署FFmpeg 和 SRS
前言 用户对网络做了限制,只能访问指定的网址,和没网没啥区别,导致无法连接外网,无法获取安装包,还有一些编译需要的开源工具 用户需要用平台查看库房的海康摄像头实时监控,只能在库房里一台纯净的ubantu…...

NOBLEROYCE罗慕路斯门窗 以精工匠造开启私属人生
公元前753年罗马建立,其创建者为罗慕路斯。以狼孩的传奇形象成为古罗马精神象征的罗慕路斯,不仅是罗马的第一任国王,还创建了罗马最初的政治制度,罗马的名字也是源于这位伟大的奠基人。NOBLEROYCE罗慕路斯,致敬这位人类…...