修改8401pom.xml,将公共模块也引入
<!-- 公共模块 --> <dependency> <groupId>com.polaris</groupId> <artifactId>cloud-api-common</artifactId> <version>${project.version}</version> </dependency>新增业务类RateLimitController,便于演示
@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,就跑到我们自定义的限流处进行限流
测试:出现了我们自定义的限流兜底方案!
发现问题:此时如果关闭服务8401会怎样?=> Sentinel控制台流控规则消失了?临时存储?
按照Url地址限流 + 后续处理
通过访问URL来限流,会返回Sentinel自带默认的限流处理信息
业务类增加
@GetMapping("/rateLimit/byUrl") @SentinelResource(value = "byUrl") public CommonResult byUrl() { return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002")); }配置流控规则
测试:会返回Seninel自带的限流处理结果:Blocked by Sentinel (flow limiting)
上述兜底方案面临的问题
系统默认的方案,没有体现我们自己的业务需求
依照现有条件,我们自定义的处理方法又和业务代码耦合在一起,不直观
每个业务方法都添加一个兜底方法,会导致代码膨胀加剧
全局统一的处理方法没有体现
客户自定义限流处理逻辑
创建CustomerBlockHandler类用于自定义限流处理逻辑
public class CustomerBlockHandler { public 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"); } }RateLimitController增加方法
@GetMapping("/rateLimit/customerBlockHandler") @SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerException2") public CommonResult customerBlockHandler() { return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003")); }测试:出现了我们自定义的限流兜底方案!
@SentinelResource的其他属性
属性 作用 是否必须value 资源名称 是
entryType entry类型,标记流量的方向,取值IN/OUT,默认是OUT 否
blockHandler 处理BlockException的函数名称。函数要求:
1. 必须是 public
2.返回类型与原方法一致
3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。
4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。
否
blockHanderClass 存放blockHandler的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同blockHandler。 否
fallback 用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
1. 返回类型与原方法一致
2. 参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。
3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。
否
fallbackClass (1.6) 存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。 否
defaultFallback 用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求:
\1. 返回类型与原方法一致
\2. 方法参数列表为空,或者有一个 Throwable 类型的参数。
\3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。
否
exceptionTolgnore (1.6) 指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。 否
exceptionsToTrace 需要trace的异常 Throwable
注意:
1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。