Sentinel的@SentinelResource

发布于 2022-04-22  1.6k 次阅读


@SentinelResource用于定义资源,并提供可选的异常处理和fallback配置项

注解属性:

1,value:资源名称,必选项(不能为空),假如没有SentinelResource注解可以使用URL作为限流资源名称

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

3,blockHandler / blockHandlerClass:blockHandler对应处理BlockException的函数名称,可选项,blockHandler函数的访问范围需要是public,返回类型需要和原方法匹配,参数类型也需要和原方法匹配并且需要加一个额外参数,类型为BlockException,blockHandler函数默认需要和原方法在一个类中,若想解耦需要指定一个blockHandlerClass,这个类中的方法必须为static静态否则无法解析

4,fallback:fallback函数的名称,可选项,对于在抛出异常的时候提供fallback处理逻辑,fallback函数可以针对所以类型的异常(除了exceptionToIgnore里面排除的异常)进行处理

fallback函数的签名和位置要求:

  • 返回值类必须要和原方法返回值类型一致
  • 方法参数列表需要和原函数一致,或者可以额外多一个Throwable类型的参数用于接收对应的异常
  • fallback函数默认需要和原方法在同一个类中,若希望使用其他类的函数则可以使用fallbackClass为对应的类的Class对象,这个类的函数必须要为static否则无法解析

5,defaultFallback:默认的fallback函数名称,可选项,通常用于通用的fallback逻辑(不指定具体的fallback使用这个默认),假如defaultFallback和fallback一起配置,则只要fallback生效

defaultFallback函数的签名和位置要求:

  • 返回值类型必须与原函数返回值类型一致
  • 方法参数列表需要为空,或者可以额外添加一个Throwable类型的参数用于接收异常
  • ExceptionToIgnore:用于指定那些异常可以被排除,不会计入异常统计中,不能针对业务异常进行处理

若BlockHandler和Fallback都进行了配置,则被限流降级而抛出的BlockException只会进入blockHandler处理逻辑,若未配置blockHandler,fallback和denfaultFallback,则被限流降级时会将BlockException直接抛出

一,@SentinelResource简单使用

例:

@GetMapping("/ByResource")
@SentinelResource(value = "ByResource",blockHandler = "ByHandler")
public CommonResult ByResource(){
    return new CommonResult(200,"对指定资源进行限流");
}

public CommonResult ByHandler(BlockException blockexception){//兜底方法异常必须要加
    return new CommonResult(444,"服务不可用被限流");
}

设置:

访问:频繁访问导致限流

二,@SentinelResource解耦

默认@SentinelResource兜底方案面临的问题:

  • 系统默认的,不同体现业务需求
  • 限流方法和兜底方法在同一个类中,处理方法和业务方法耦合
  • 每一个业务方法都添加兜底,那么代码会膨胀
  • 全局统一处理方法没有体现

Sentinel提供了blockHandlerClass属性来解决这些问题(如:统一处理,方法耦合)

  • blockHandlerClass:指定处理类(和blockHandler配合使用)
  • fallbackClass:指定处理类(和fallback配合使用)

例:

①处理类

public class customerBlockHandler {

    public static CommonResult ByHandler(BlockException blockexception){ //一定要加static
        return new CommonResult(444,"服务不可用被限流");
    }
}

② 业务类

@GetMapping("/ByResource")
@SentinelResource(value = "ByResource",blockHandlerClass = customerBlockHandler.class,blockHandler = "ByHandler")//blockHandlerClass指定处理类,blockHandler指定处理方法
public CommonResult ByResource(){
    return new CommonResult(200,"对指定资源进行限流");
}

③ 设置

④ 测试

三,fallback和blocakHandler的使用区别

  • fallback:负责业务异常,如:空指针,OOM等java业务异常
  • blockHandler:负责控制台违规异常,如触发限流异常

例:

@GetMapping("/ByResource")
@SentinelResource(value = "ByResource",blockHandler = "ByHandler",fallback ="ByFallback" )
public CommonResult ByResource(){
    int t = 10/0;//异常代码
    return new CommonResult(200,"对指定资源进行限流");
}
public  CommonResult ByHandler(BlockException blockexception){ //一定要加static
    return new CommonResult(444,"控制台规则");
}
public  CommonResult ByFallback(Throwable throwable){ //一定要加static
    return new CommonResult(445,"业务异常");
}

四,Sentinel和OpenFeign整合

① maven依赖

<!--实现服务的注册与发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--sentinel服务限流降级框架-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<!--OpenFeign依赖包-->
<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>

② application配置

server:
  port: 9107
spring:
  application:
    name: cloudalibaba-SentinelMain-OpenFeign
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.68.134:8084 #nacos服务端地址,Nginx做了代理
    sentinel:
      transport:
        dashboard: localhost:8080 #SentinelMain dashboard地址
        port: 8719 #默认端口为8719,如果被占用开始+1扫描,直到找到未被占用的端口
feign:
  sentinel: #开启对sentinel的支持
    enabled: true

③ main启动类

@SpringBootApplication
@EnableDiscoveryClient //Nacos注册发现
@EnableFeignClients //OpenFeign的支持
public class SentinelOpenfeignMain {
    public static void main(String[] args) {
        SpringApplication.run(SentinelOpenfeignMain.class,args);
    }
}

④ openfeign

//feign调用类
@FeignClient(value = "cloudalibaba-sentinelmain-service",fallback = FallBackServiceImpl.class)
public interface OpenFeignService {

    @RequestMapping("/testA") //这个/testA是一个有异常的方法
    String getNacosProvider();
}
//处理类
@Component
public class FallBackServiceImpl implements OpenFeignService {
    @Override
    public String getNacosProvider() {
        return "OpenFeign Sentinel 整合--->FallBack触发";
    }
}

⑤ controller

@RestController
public class Sentinelfeigncontroller {


    @Autowired
    OpenFeignService openFeignService;


    @GetMapping("/getProvider")
    public String getProvider(){

        String nacosProvider = openFeignService.getNacosProvider();
        return nacosProvider;
    }

测试:


路漫漫其修远兮,吾将上下而求索