当前位置: 首页 > news >正文

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第十三章&#xff0c;升级篇&#xff0c;服务降级、熔断和限流Sentinel 一、Sentinel概述 1、Sentinel是什么 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保…...

【k8s 深入学习之 event 聚合】event count累记聚合(采用 Patch),Message 聚合形成聚合 event(采用Create)

参考 15.深入k8s:Event事件处理及其源码分析 - luozhiyun - 博客园event 模块总览 EventRecorder:是事件生成者,k8s组件通过调用它的方法来生成事件;EventBroadcaster:事件广播器,负责消费EventRecorder产生的事件,然后分发给broadcasterWatcher;broadcasterWatcher:用…...

leetcode104.二叉树的最大深度

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;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开发背景 传统的管理方式都在使用手工记录的方式进行记录&#xff0c;这种方式耗时&#xff0c;而且对于信息量比较大的情况想要快速查找某一信息非常慢&#xff0c;对于会员制医疗预约服务信息的统计获取比较繁琐&#xff0c;随着网络技术的发展&#xff0c;采用电脑…...

android studio 读写文件操作(应用场景二)

android studio版本&#xff1a;2023.3.1 patch2 例程&#xff1a;readtextviewIDsaveandread 本例程是个过渡例程&#xff0c;如果单是实现下图的目的有更简单的方法&#xff0c;但这个方法是下一步工作的基础&#xff0c;所以一定要做。 例程功能&#xff1a;将两个textvi…...

小尺寸低功耗蓝牙模块在光伏清扫机器人上的应用

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

防火墙有什么作用

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

MongoDB-BSON 协议与类型

前言&#xff1a; MongoDB 是一个高性能、无模式的 NoSQL 数据库&#xff0c;广泛应用于大数据处理和实时数据存储。作为一个数据库系统&#xff0c;MongoDB 的核心之一就是其使用的 BSON&#xff08;Binary JSON&#xff09;格式&#xff0c;它用于存储数据以及在客户端和数据…...

学习threejs,使用VideoTexture实现视频Video更新纹理

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️VideoTexture 视频纹理 二、…...

怎么获取键值对的键的数值?

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

数据结构排序算法详解

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

在Linux设置postgresql开机自启动,创建一个文件 postgresql-15.service

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

【kafka】消息队列的认识,Kafka与RabbitMQ的简单对比

什么是消息队列&#xff1f; 消息队列&#xff08;Message Queue&#xff0c;简称 MQ&#xff09;是一个在不同应用程序、系统或服务之间传递数据的机制。 它允许系统间异步地交换信息&#xff0c;而无需直接交互&#xff0c;确保消息的可靠传输。 想象一下&#xff0c;你正在…...

ProjectSend 身份认证绕过漏洞复现(CVE-2024-11680)

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

Android笔记(三十四):onCreate执行Handler.post在onResume后才能执行?

背景 偶然发现一个点&#xff0c;就是在onCreate执行Handler.post在onResume后才执行&#xff0c;以下是测试代码 多次运行的结果一致&#xff0c;为什么execute runnable不是在onCreate和onResume之间执行的呢&#xff0c;带着疑问撸了一遍Activity启动流程 关键源码分析 …...

关闭模组的IP过滤功能

关闭模组的IP过滤功能 关闭模组的IP过滤功能 本脚本用于关闭模组的IP过滤功能&#xff0c;关闭后&#xff0c; 源地址不是终端IP的数据包&#xff0c;也可以被模组转发给网络 关闭模组的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对象…...

一番赏小程序定制开发,打造全新抽赏体验平台

随着盲盒的热潮来袭&#xff0c;作为传统的潮玩方式一番赏也再次受到了大家的关注&#xff0c;市场热度不断上升&#xff01; 一番赏能够让玩家百分百中奖&#xff0c;商品种类丰富、收藏价值高&#xff0c;拥有各种IP&#xff0c;从而吸引着各个圈子的粉丝玩家&#xff0c;用…...

【前端】将vue的方法挂载到window上供全局使用,也方便跟原生js做交互

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

Oracle查询优化:高效实现仅查询前10条记录的方法与实践

在 Oracle 中&#xff0c;实现仅查询前10条记录的四种方法 1. 使用 ROWNUM 查询 ROWNUM 是 Oracle 中的伪列&#xff0c;用于限制返回的行数。 SELECT * FROM table_name WHERE condition AND ROWNUM < 10;condition&#xff1a;查询条件。ROWNUM < 10&#xff1a;限制…...

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 环境变量&#xff0c;以下三选一 七牛 CDN go env -w …...

mobi文件转成pdf

将 MOBI 文件转换为 PDF 格式通常涉及两个步骤&#xff1a; 解析 MOBI 文件&#xff1a;需要提取 MOBI 文件的内容&#xff08;文本、图片等&#xff09;。将提取的内容转换为 PDF&#xff1a;将 MOBI 文件的内容渲染到 PDF 格式。 可用工具 kindleunpack 或 mobi&#xff1…...

MobaXterm解决中文显示乱码问题

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

西门子 SINAMICS G120 变频器借助 ProfiNet 转 EtherCAT 实现与汇川 H5U 通讯实例

一&#xff0e; 案例背景 随着智能制造理念的推进&#xff0c;设备之间的协同工作变得越来越重要。例如&#xff0c;在机器人自动化焊接生产线中&#xff0c;电机驱动的焊接机器人需要与其他设备协同工作&#xff0c;这就要求负责电机控制的变频器和控制整个生产线流程的PLC能…...

流媒体之linux下离线部署FFmpeg 和 SRS

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

NOBLEROYCE罗慕路斯门窗 以精工匠造开启私属人生

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