[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)

SpringCloud Alibaba Sentinel的入门及使用

一、Sentinel简介

sentinel源码

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

相较于Hystrix来说,Sentinel是不需要手工搭建,是独立的,可以有界面化的细粒度统一配置。

二、运行Sentinel

1.下载jar包

下载地址

下载dashboard

2.运行jar包

java -jar sentinel-dashboard-1.7.2.jar

3.进入图形化界面

http://localhost:8080/

端口号和tomcat是一样的

三、Sentinel功能模块创建

1.创建子模块

创建子模块cloudalibaba-sentinel-service8401

2.修改pom文件

    <dependencies>
        <dependency>
            <groupId>com.xiaoxiao.springcloudgroupId>
            <artifactId>cloud-api-commonartifactId>
            <version>${project.version}version>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cspgroupId>
            <artifactId>sentinel-datasource-nacosartifactId>
        dependency>
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
            <version>4.6.3version>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>

    dependencies>

3.修改yml文件

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719


management:
  endpoints:
    web:
      exposure:
        include: '*'



4.编写主方法

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

5.编写controller测试

@RestController
@Slf4j
public class FlowLimitController {

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

6.观察Sentinel控制台

观察控制台可以发现,一开始是没有任何显示和监控的。

sentinel使用的加载机制是懒加载机制,需要有请求以后才开始监控。

四、sentinel监控管理

1.流控规则

文档

一般建立流控有两种方式

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第1张图片
[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第2张图片

1.QPS直接流控

QPS代表一秒内的访问数

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第3张图片

就比如这里,代表一秒通过的访问数最多为1个,如果超过阈值,直接限流。

2.线程数进行流控

根据进入的线程数阈值进行管控,如果超过阈值则进行限流。

3.关联流控

如果设置关联,当关联的资源达到阈值,会限流他自己

4.warm up预热

假设系统长期处于低水平运转,如果系统突然高并发,会在一定时间内缓慢增加到阈值

阈值类型需要设置成QPS

预热时初始阈值:阈值/coldFactor(coldfactor默认是3)

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第4张图片

举例来说,假设设置阈值为10,预热时间为5

那么初始阈值就是10/3等于3,在5秒后缓慢将阈值升为10

5.匀速排队

阈值类型必须设置成QPS

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第5张图片

这里是将排队QPS个数设置为1个,一秒只能通过一个QPS,超过1000ms不等待直接超时限流。

2.降级规则

熔断降级

我们通常用以下几种方式来衡量资源是否处于稳定的状态:

  • 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
  • 异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。

降级策略有三种:

  • RT

    平均响应时间,秒级,满足条件平时响应时间超出阈值且在时间窗口内的通过的请求>=5触发降级

  • 异常比例

    秒级,QPS>=5且异常比例超过阈值,触发降级;时间窗口时间结束后再关闭降级

  • 异常数

    每分钟异常数超过阈值触发降级,时间窗口期结束后结束熔断,由于按分钟计算,如果再次出现异常有可能再次进入熔断

时间窗口就是如果达到降级规则要求,断路器开启时间。

断路器开启期间所有请求都会被自动降级熔断,默认抛出异常degradeException

1.RT

如果1S内进入的请求>=5且处理响应时间大于等于阈值,就会触发降级
[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第6张图片

这里就是在未来的1s内,如果超过5个请求,且处理时间大于200ms,就会触发降级

2.异常比例

如果每秒异常比例超过阈值,就在指定时间窗口内进入降级

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第7张图片

这里意思就是,如果一秒内请求异常比例>20%就会在未来的3秒内触发降级

3.异常数

如果每分钟异常数量超过阈值,则在指定时间窗口时间内进入降级

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第8张图片

这里意思就是,在一分钟内如果产出异常数超过阈值,就进入降级状态,时间为时间窗口设置时间

3.热点规则

热电参数限流简介

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

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

1.指定参数进行限制

这里注意,如果导包要com.alibaba.csp.sentinel.slots.block.BlockException,而不是BlockedException,不要导包导错了,否则不会调用降级方法而是直接返回errorpage

    @GetMapping("/testHotkey")
    @SentinelResource(value = "testHotkey",blockHandler = "deal_blockHandler")//降级处理注解
    //value要与调用资源一致,降级方法设置属性是deal_blockHandler
    public String testHotkey(
            @RequestParam(value = "v1",required = false)String v1,
            @RequestParam(value = "v2",required = false)String v2) {
        return "-----------testHotkey";
    }
    //降級方法,参数类型与个数与调用方法一致,如果返回错误,说明没有加BlockException,或者导包BlockedException
    public String deal_blockHandler(String v1, String v2, BlockException excption) {
        return "----------deal_blockHandlero(╥﹏╥)o";
    }

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第9张图片

1.资源名要与@SentinelResource的value属性一致

2.参数索引就是参数是第一个,从0开始

3.单机阈值是一秒传来的请求数量

4.窗口时长就是限制时间,在这段时间将所有请求直接降级处理

2.参数例外项

参数例外项就是设置某个参数阈值后,设置参数例外项阈值,满足这个特定的参数的话以参数例外项阈值为标准。

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第10张图片

这里意思就是,如果第一个参数传进来,QPS超过1就进入5s的熔断,但是如果参数是5,QPS>=5才会进入熔断。

4.系统自适应限流

上面叙述的都是细粒化的限流,系统自适应限流是对整个系统进行限流

官方文档给出以下5种方式

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

  • 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 达到阈值即触发系统保护。

五、@SentinelResource注解详解

注解详解摘自官网:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81

注意:注解方式埋点不支持 private 方法。

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

  • value:资源名称,必需项(不能为空)

  • entryType:entry 类型,可选项(默认为 EntryType.OUT)

  • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

  • fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:

    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。-
  • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:

    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

    注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

1.更改模块

1.加入自定义类pom

这里导入了自定义依赖

<dependency>
    <groupId>com.xiaoxiao.springcloudgroupId>
    <artifactId>cloud-api-commonartifactId>
    <version>${project.version}version>
dependency>

2.新建controller

@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 服务不可用");
    }

    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl() {
        return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002"));
    }

}

2.按资源名限流

@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 服务不可用");
}

@SentinelResource(value = “byResource”, blockHandler = “handleException”)这里注解是按照资源名来限流,所以value是byResource,默认降级方法调用handleException

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eGuvHw2u-1593828681600)(D:\学习笔记\springcloud\imgs\alibaba\资源名.jpg)]

3.按url限流

@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
    return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002"));
}

@SentinelResource(value = “byUrl”),使用资源路径/rateLimit/byUrl进行控流,没有指定降级方法,默认调用系统默认,返回网页Blocked by Sentinel (flow limiting)。

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第11张图片

4.自定义降级方法

如果指定降级方法,代码比较冗余。这时候就可以利用注解@SentinelResource来解决

1.自定义blockHandler类

public class CustomerBlockHandler {
    public static CommonResult myBlockHandler1(BlockException excption) {
        return new CommonResult(444, "自定义handler处理器......myBlockHandler1", new Payment(2020L, "seriall10"));
    }
    public static CommonResult myBlockHandler2(BlockException excption) {
        return new CommonResult(424, "自定义handler处理器......myBlockHandler2", new Payment(2020L, "serial120"));
    }
}

注意参数要配置BlockException excption,否则会出现error:com.alibaba.csp.sentinel.slots.block.flow.FlowException: null

2.使用定制blockHandler类

@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
        blockHandlerClass = CustomerBlockHandler.class, //指定定制blockHandler类
        blockHandler = "myBlockHandler1")   //指定使用定制blockHandler类中的方法myBlockHandler1作为降级处理方案
public CommonResult customerBlockHandler() {
    return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003"));
}

blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

这里一定要注意如果要使用别的类的blockHandler ,对应的函数要是static!!!

六、sentinel服务熔断

1.创建子模块

创建两个服务提供者子模块和一个消费者模块

1.服务提供模块

1.改pom文件
<dependencies>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    <dependency>
        <groupId>com.xiaoxiao.springcloudgroupId>
        <artifactId>cloud-api-commonartifactId>
        <version>${project.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>
2.编写yml文件
server:
  port: 9003

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址

management:
  endpoints:
    web:
      exposure:
        include: '*'

3.编写主方法
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003 {
    public static void main(String[] args){
        SpringApplication.run(PaymentMain9003.class,args);      
        
    }
}
4.编写controller
@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,"111111111111"));
        hashMap.put(2L,new Payment(2L,"2222222222222"));
        hashMap.put(3L,new Payment(3L,"3333333333333"));
    }

    @GetMapping(value = "/payment/{id}")
    public CommonResult<Payment> payment(@PathVariable("id") Long id)
    {
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }
}

2.服务消费者模块

1.改pom
<dependencies>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    <dependency>
        <groupId>com.xiaoxiao.springcloudgroupId>
        <artifactId>cloud-api-commonartifactId>
        <version>${project.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>
2.编写yml
server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true
3.编写主方法
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderMain84 {
    public static void main(String[] args){
        SpringApplication.run(OrderMain84.class,args);      
    }
}
4.实现openfien负载均衡

编写service

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {
    @GetMapping(value = "/payment/{id}")
    public CommonResult<Payment> payment(@PathVariable("id") Long id);
}
//兜底fallback
@Component
public class PaymentFallbackService implements PaymentService {
    @Override
    public CommonResult<Payment> payment(Long id) {
        return new CommonResult(444,"我挂了,我的id是:  "+id,new Payment(id,"error"));
    }
}

配置负载均衡

@Configuration
public class MyConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getreRestTemplate() {
        return new RestTemplate();
    }
}
5.编写controller
@RestController
@Slf4j
public class OrderController {
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/payment/"+id,CommonResult.class,id);

        if (id <= -1) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }

        return result;

}

2.服务熔断设置

服务熔断的设置是以@SentinelResource注解来进行操作

1.不设置任何参数

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback") //不做配置
public CommonResult<Payment> fallback(@PathVariable Long id)

如果抛出异常,直接返回errorpage

[SpringCloud Alibaba学习笔记]Sentinel的入门,配置及使用(结合openfeign,nacos)_第12张图片

2.仅设置fallback

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback负责处理异常
public CommonResult<Payment> fallback(@PathVariable Long id)
public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
    Payment payment = new Payment(id,"null");
    return new CommonResult<>(444,"兜底异常handlerFallback,异常信息:  "+e.getMessage(),payment);
}

如果出现异常,会执行兜底方法handlerFallback

如果设置Sentinel配置监控,超出阈值也会调用这个兜底方法,但是异常信息为空

3.仅设置blockHandler

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    public CommonResult<Payment> fallback(@PathVariable Long id)
//blockHandler
public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
    Payment payment = new Payment(id,"null");
    return new CommonResult<>(445,"blockHandler.....sentinel限流,blockException :  "+blockException.getMessage(),payment);
}

如果出现Sentinel配置的违规,会进入blockHandler进行执行

但如果出现异常,不由blockHandler处理,而是直接进入errorpage.

blockHandler优先级要高于errorpage,只要一满足Sentinel阈值,又去执行blockHandler

4.设置fallback和blockHandler

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler")//都设置
    public CommonResult<Payment> fallback(@PathVariable Long id)

如果有异常,就执行fallback,有出现Sentinel配置的违规,就执行blockHandler.

但是如果异常执行过多达到Sentinel配置的阈值,就执行blockHandler.

七、规则持久化

使用Sentinel的过程中发现,如果重启微服务,则设置的规则会消失.

所以需要数据库将规则进行存储.

这里使用nacos对规则配置进行存储.

1.增加依赖

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
dependency>

2.修改yml

以上文设置的8401微服务为例

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719
      #将Sentinel放入nacos的数据库
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service	#配置名
            groupId: DEFAULT_GROUP	#groupid
            data-type: json	#以json存储
            rule-type: flow	#限流

management:
  endpoints:
    web:
      exposure:
        include: '*'

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



3.nacos远程新建配置

[
    {
        "resource": "byResource",
        "limitApp": "default",
        "grade": 1,
        "count": 2,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]
  • resource:资源名
  • limitApp:流控针对的调用来源,default不区分来源
  • grade:阈值类型(0根据线程数来限流,1根据QPS来进行流量控制)
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流控效果(0直接拒绝、1WarmUP、2匀速排队)
  • clusterMode:是否集群模式

八、总结

1.学习总结

Sentinel哨兵能够对微服务进行实时监控,并有一些列规则进行限流,降级,熔断,还有一些如热点规则等功能.能够将定义的规则和nacos进行结合实现持久化.

2.注意事项

1.自定义降级方法的时候要注意:

blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

2.如果@SentinelResource注解无法生效,可以尝试重启微服务

3.如果nacos远程配置读取无效,可以尝试重启,或者看我的博客

你可能感兴趣的:(学习笔记,SpringCloud,Alibaba,JAVA)