Sentinel熔断与限流

1、简介

在线文档:

https://sentinelguard.io/zh-cn/docs/system-adaptive-protection.html

功能:

  • 流量控制
  • 速率控制
  • 熔断和限流

和Hystrix的区别:

  • Hystrix需要手动搭建监控平台

    (Dashboard:对Hystrix进行图形化的监控)

  • 没有web界面配置

2、快速开始

注:不能将Sentinel部署在云服务器上,因为下面的quickstart需要sentinel访问项目的ip,外网无法访问内网ip,所以我推荐你使用widnows的docker来完成下面的操作。

①安装启动

启动Nacos:

docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=256m -e JVM_XMX=256m -e JVM_XMN=128m -p 8848:8848 -d nacos/nacos-server

安装启动Sentinel:

#拉取sentinel镜像
docker pull bladex/sentinel-dashboard
#运行sentinel(docker里的sentinel是8858端口)
docker run --name sentinel -d -p 8858:8858 bladex/sentinel-dashboard

进入控制台:

image-20230202172726342

②Server工程

1.新建模块cloudalibaba-sentinel-service8401

2.依赖:

<dependencies>
<!-- SpringCloud ailibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</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>

3.yml:

经过我个人的测试,docker下cleint-ip设置为localhost或者127.0.0.1都会出现监控和dashboard完全相同的问题,查看网络的局域网ip填写可以正常显示

server:
port: 8401
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址(改成自己的服务器ip地址,本地用localhost‍)
#server-addr: 101.43.244.40:8848
server-addr: localhost:8848
sentinel:
transport:
#配置Sentin dashboard地址(改成自己的服务器ip地址,本地用localhost‍)
dashboard: localhost:8858
client-ip: 192.168.31.30
#client-ip: 127.0.0.1
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'

4.启动类:

@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401 {
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}

5.Controller:

@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA() {
return "----testA";
}
@GetMapping("/testB")
public String testB() {
return "----testB";
}
}

6.启动:

访问testA和testB接口

image-20230202173749299

查看sentinel控制台:

image-20230202214523148

3、流控规则

流量控制(flow control)其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

①新建流控规则

1.在流控规则处创建

image-20230203101415345

2.在簇点链路中创建

image-20230203101644883

流控效果检查:

image-20230203101723755

②阈值类型

QPS:每秒的请求数

线程数:调用该API的并发线程数

③流控模式

一.直接

对该资源进行限流

image-20230203102517401

二.关联

使用关联模式,当关联资源/testB达到了阈值1,testA也会被限流。

image-20230203103309514

删除testB的直接模式的限流,只保留关联模式限流:

因为关联模式只会对testA限流,不对testB限流,如果保留testB限流QPS条件,那么关联模式限流的阈值无法达到。

image-20230203104801870

使用Jmeter测试:

image-20230203105052486

启动Jmeter压测,访问testA接口,此时testA被限流,关联模式测试完成:

image-20230203105140367

三.链路

只针对指定的链路进行统计限流

比如testA,testB,都调用childTest接口,所以存在两条链路testA->childTest和testB->childTest。

假如我只想对testA->childTest这条链路进行限流:

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

去配置文件里配置,关闭context,就可以让controller里的方法单独成为一个链路;不关闭context的话,controller里的方法都会默认进去sentinel默认的根链路里,这样就只有一条链路,无法流控链路模式,如下图所示:

image-20230203105932976

service.TestService:

@Service
public class TestService {
@SentinelResource("childTest")
public String childTest(){
return "child";
}
}

修改Controller:

@RestController
public class FlowLimitController {
@Resource
private TestService testService;
@GetMapping("/testA")
public String testA() {
return "----testA"+testService.childTest();
}
@GetMapping("/testB")
public String testB() {
return "----testB"+testService.childTest();
}
}

修改yml,关闭context(没有提示):、

这里存在问题:1.6.3-1.7.0之间的Sentinel,此注释无效

从1.6.3 版本开始,Sentinel Web filter 默认收敛所有URL的入口 context,因此链路限流不生效。

1.7.0 版本开始(对应SCA的2.1.1.RELEASE),官方在 CommonFilter 引入了WEB_CONTEXT_UNIFY 参数,用于控制是否收敛context。将其配置为 false 即可根据不同的URL 进行链路限流。

解决办法:

修改Springcloud alibaba的版本号:

image-20230203111539522

如果无法识别注释,为上述问题,需要解决。

image-20230203111635416

启动,如下图所示,即为关闭了context收敛:

image-20230203111839117

配置链路模式流量控制,对于childTest的testA入口进行流量限制:

image-20230203112214485

对testA入口进行压测:

image-20230203112255449

结果如下:

childTest对于testB入口无流量限制,而对于testA入口存在流量限制:

image-20230203113039135

image-20230203113228418

④流控效果

一.快速失败

直接失败,抛出异常

二.预热

应用场景:系统刚开启,秒杀等

公式:阈值/coldFacotr(默认为3)

默认冷加载因子为3,即请求QPS从threshold/3开始,经过预热时长逐渐升到设定的限流,冷启动

例:

设置预热,阈值为6,最初的阈值为6/3=2,经过10s升到6

image-20230203133651649

三.排队等待

不同于快速失败,超过QPS的会等待,设置一个超时时间,如果在时间内没有被处理,会抛出异常。

image-20230203134508721

4、降级规则

Sentinel现已支持半开状态

①慢调用比例

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

1.在Controller上添加方法:

设置休眠为1s

@GetMapping("/testC")
public String testC() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("testC 测试RT");
return "----testC";
}

2.设置Sentinel降级为慢比例调用

image-20230203140845126

Jmeter测试:

image-20230203141257525

后面如果服务正常,可以进行半开测试,如果下一次请求小于最大响应时间,服务熔断恢复

②异常比例

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

image-20230203141843801

Controller添加异常模拟方法:

@GetMapping("/testD")
public String testD() throws Exception {
double random = (int)(Math.random()*10);
if (random==0) throw new Exception("异常模拟");
log.info("testD 测试比例异常");
return "----testD";
}

设置Sentinel服务降级为异常比例:

image-20230203143016634

测试:

使用Jmeter进行测试,当到达异常比例,进入熔断状态,5s后使用浏览器调用接口,进入半开状态,此时使用浏览器调用接口,接口返回正常,断路器从半开状态进行关闭状态。

image-20230203143215821

③异常数

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

使用②中Controller的方法,Sentinel配置:

image-20230203144134574

同②的测试,当异常数达到了一定值,进入熔断状态,5s后使用浏览器调用接口,进入半开状态,此时使用浏览器调用接口,接口返回正常,断路器从半开状态进行关闭状态。

image-20230203144618918

5、热点规则

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。

热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

在前面的Hystrix中,当降级时会有fallbcak方法,在Sentinel同样存在这样的兜底方法定义方式:@SentinelResource

①使用blockHandler

1.依赖(默认包含):

image-20230203145727917

2.Controller添加方法:

@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) {
return "----testHotKey";
}
//兜底方法
public String deal_testHotKey(String p1, String p2, BlockException exception) {
// sentinel的默认提示都是: Blocked by Sentinel (flow limiting)
return "----deal_testHotKey, o(╥﹏╥)o";
}

Sentinel设置:

image-20230203150821230

②不使用blockHandler

不使用blockHandler,当达到阈值,进入窗口时,会直接跑出异常,返回500错误

image-20230203151510180

③参数例外项

在上面的热点规则设置中,当对应参数QPS达到一定阈值后就会被限流。对参数进行特定例外项设置,特定参数具有特地的QPS限制:

image-20230203155714521

Jmeter测试:

发起50个请求,p1=5,前40个请求正常处理,最后的10个请求出错:

image-20230203155849724

④blockHanlder与异常

不同于Hystrix的fallback,blockHandler不会自动对异常进行兜底方法处理,如果方法出错,而未满足Sentinel的控制台设置,会返回500错误

@SentinelResouce:

处理的是Sentinel控制台配置的违规情况,使用blockHandler进行兜底处理

6、系统规则

个人理解为:对整个应用的入口的流量的控制

系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

系统规则支持以下的模式:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

对入口QPS进行限制测试:

image-20230203161607541

仅做测试,实际测试和效果不对应:

如下,QPS阈值引起的限流

image-20230203161757534

7、@SentinelResource

前置操作:

8401引入commons依赖

<dependency>
<groupId>cn.zko0.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

新建一个RateLimitController

@RestController
public class RateLimitController {
}

①按资源名称限流

@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200,"按照资源名称限流测试",new Payment(2020L,"serial001"));
}
//兜底方法
public CommonResult handleException(BlockException exception) {
return new CommonResult(444,exception.getClass().getCanonicalName() + "\t 服务不可用");
}

在Sentinel中进行配置限制

image-20230203163805979

测试,成功:

QPS超过1,会使用blockHandler方法

image-20230203163908745

②按照URL地址限流

在Controller中添加接口:

@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl") //没有兜底方法,系统就用默认的
public CommonResult byUrl() {
return new CommonResult(200,"按照byUrl限流测试",new Payment(2020L,"serial002"));
}

在Sentinel中设置:

image-20230203164248499

测试:

image-20230203164308055

③blockHandler问题解决

blockHandler问题:

  • 系统默认,不能体现业务
  • 自定义方法和业务代码耦合在一起
  • 每个代码都需要兜底方法,代码膨胀
  • 没有全局的统一处理

解决:

自定义blockHandler类

public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception) {
return new CommonResult(444,"按照客户自定义限流测试,Glogal handlerException ---- 1");
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(444,"按照客户自定义限流测试,Glogal handlerException ---- 2");
}
}

使用blockHandlerClassblockHandler对兜底方法和业务代码进行解耦:

@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200,"按照客户自定义限流测试",new Payment(2020L,"serial003"));
}

在Sentinel中使用资源名称方式,进行限流(使用URL无法使用自定义兜底方法):

image-20230203164953269

测试,完成:

image-20230203165008956

8、服务熔断(Ribbon)

①Ribbon(无配置)

一.Provider

1.新建模块cloudalibaba-provider-payment9003

2.pom依赖:

<dependencies>
<!-- SpringCloud ailibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud ailibaba sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>cn.zko0.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</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>

3.yml:

server:
port: 9003
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos
management:
endpoints:
web:
exposure:
include: '*'

启动类:

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9003.class,args);
}
}

Controller:

@RestController
public class PaymentController {
@Value("${server.port}") //spring的注解
private String serverPort;
public static HashMap<Long, Payment> map = new HashMap<>();
static {
map.put(1L,new Payment(1L,"1111"));
map.put(2L,new Payment(2L,"2222"));
map.put(3L,new Payment(3L,"3333"));
}
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {
Payment payment = map.get(id);
CommonResult<Payment> result = new CommonResult<>(200,"from mysql,serverPort: " + serverPort,payment);
return result;
}
}

按照创建9003的方式创建9004

二.Consuemr

1.创建项目cloudalibaba-consumer-nacos-order84

2.pom:

<dependencies>
<!-- SpringCloud ailibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud ailibaba sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>cn.zko0.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</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>

3.yml:

server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos
sentinel:
transport:
dashboard: localhost:8858 #sentinel
client-ip: 192.168.31.30
port: 8719
#消费者将去访问的微服务名称
server-url:
nacos-user-service: http://nacos-payment-provider
#激活Sentinel对Feign的支持
#feign:
# sentinel:
# enabled: true

启动类:

@EnableDiscoveryClient
@SpringBootApplication
public class OrderMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderMain84.class,args);
}
}

RestTemplate的Config:

@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

Controller:

@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback") //没有配置
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("IllegalArgument,非法参数异常...");
}else if(result.getData() == null) {
throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
}

三.启动测试

启动

Provider:9003,9004 Consumer:84

当id在1-4范围内,服务正常调用

image-20230203204601892

当服务id>=5,调用出错:

image-20230203205819316

②Ribbon只配置fallback

在前面的Ribbon搭建的结果上,对id>=5的问题配置fallback,进行服务降级处理:

image-20230203210157168

//fallback兜底
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult(444,"异常handlerFallback,exception内容: " + e.getMessage(), payment);
}

测试,服务降级成功:

image-20230203210345422

③Ribbon只配置blockHandler

去掉上面fallback的配置

image-20230203210849040

//blockHandler兜底
public CommonResult blockHandler(@PathVariable Long id, BlockException e) {
Payment payment = new Payment(id,"null");
return new CommonResult(444,"blockHandler-sentinel 限流,BlockException: " + e.getMessage(), payment);
}

在Sentinel中配置服务降级:

image-20230203211416334

当异常数达到阈值,就会进行服务熔断

服务熔断效果:

image-20230203211612926

④Ribbon配置fallback和blockHandler

先说结论:当fallback和blockHandler同时满足,会优先调用blockHandler

同②,③,将两者配置都打开

image-20230203212010158

进行Sentinel对接口进行流量控制设置:

image-20230203213317679

测试:

当id=1,QPS未达到阈值,正常调用:

image-20230203214430518

当id=1,QPS达到阈值,调用blockHandler方法:

image-20230203214419700

当id=5,QPS未达到阈值,调用fallback方法:

image-20230203214724304

当id=5,QPS达到阈值,调用blockHandler方法:

image-20230203214750708

总结:

当@SentinelResource注解fallback和blockHandler都指定后,然后同时符合,优先执行blockHandler兜底方法。

⑤忽略属性

当在@SentinelResource中配置了exceptionsToIgnore的时候,对于该异常不会调用fallback方法,进行服务降级。

image-20230203215737786

9服务熔断(Feign)

在前面Ribbon搭建的工程上进行修改

1.需要依赖:

<!--前面已添加了-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.yml添加:

#激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true

3.启动类注解添加:

主启动类上添加@EnableFeignClients

image-20230203220653074

4.PaymentService接口

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

5.PaymentFallbackService实现类,实现PaymentService接口

其实现方法为接口中对应方法的fallback方法

@Component
public class PaymentFallbackService implements PaymentService{
@Override
public CommonResult<Payment> paymentSQL(Long id) {
return new CommonResult<>(444,"服务降级返回,---PaymentFallbackService",new Payment(id,"ErrorSerial"));
}
}

修改Controller:

image-20230203221609696

启动:

如果你在这里出现了下图的错误
image-20230203223056990

在 Hoxton.SR1 中,fegin.context 接口的定义为 parseAndValidatateMetadata,而在 Hoxton.SR3 中,fegin.context 接口的定义为 parseAndValidateMetadata,就是之前版本中定义的方法名拼写错误,所以在 Hoxton.SR1 后面的版本更正过来,因此出现 Caused by: java.lang.AbstractMethodError: com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidateMetadata(Ljava/lang/Class;)Ljava/util/List; 错误。

解决方式:将 Spring Cloud 版本升至 Hoxton.SR3

image-20230203225440079

10、规则持久化

在前面的学习中,在每次停止项目的时候,Snetinel规则将会消失。所以我们需要将限流规则持久化。

我们将Sentinel规则持久化保存至Nacos中。

针对8401项目,进行修改和测试:

1.添加依赖:(之前添加过)

<!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2.yml修改:

image-20230203230055375

3.在Nacos添加Sentinel配置:

image-20230203230257145

[
{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]

上面的配置对应着Sentinel的限流配置词条:

image-20230203230415654

启动8401,去Sentinel中查看:

可以看到Nacos中配置的限流规则在启动后就能显示,完成了持久化

image-20230203230845830

posted @   yikolemon  阅读(281)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示