通过Spring Cloud集成Sentinel之流量控制及Spring Cloud集成Sentinel之服务熔断降级两篇文章,我们可以发现一个问题,当系统触发限流或者熔断时,系统排除的异常很不友好。
现在前后端分离项目,我们后端一般会封装一个公共的实体返回给前端,比如下面代码中的CommonResult
,了解到这,我们分别介绍以下@SentinelResource
注解中常用的几个参数:value
、blockHandler
、fallback
。
测试代码
@SentinelResource注解代码
@RestController
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException",fallback = "handleFallback")
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 服务不可用");
}
public CommonResult handleFallback(Throwable exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = MyHandler.class,blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200, "按资源名称限量ok", new Payment(2020L, "SERIAL001"));
}
}
异常代码
public class MyHandler {
public static CommonResult handlerException1(BlockException exception) {
return new CommonResult(4444, "按客户自定义的global handlerException---1");
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(4444, "按客户自定义的global handlerException---2");
}
}
value
value
用于指定资源名称。在Sentinel配置中,我们前面使用的api地址作为的资源名称,其实也可以通过这个value
指定资源名称。
在Sentinel中,如果以/
开头,那么便意味着通过api地址作为资源名,否则系统认为value
作为资源名。
比如这个方法
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = MyHandler.class,blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200, "按资源名称限量ok", new Payment(2020L, "SERIAL001"));
}
在sentinel配置中,指定资源名称/rateLimit/customerBlockHandler
或customerBlockHandler
是等价的。
[alt type="warning"]value
必须是唯一的[/alt]
只指定fallback
fallback
负责业务异常和限流时处理。
测试代码
@GetMapping("/fallbackOnly")
@SentinelResource(value = "fallbackOnly", fallback = "handlefallbackOnlyException")
public CommonResult fallbackOnly() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new CommonResult(200, "按资源名称限量ok", new Payment(2020L, "SERIAL001"));
}
我们触发限流规则,可以看到如下输出,已经是我们自定义的异常类,而不是系统自带的。
还有一个fallbackClass
注解,如此类似,不再赘诉。
只指定blockHandler
blockHandler
只负责sentinel控制台配置违规
测试代码
@GetMapping("/blockHandlerOnly")
@SentinelResource(value = "blockHandlerOnly", blockHandler = "handleblockHandlerException")
public CommonResult blockHandlerOnly() {
int age = 10/0;
return new CommonResult(200, "按资源名称限量ok", new Payment(2020L, "SERIAL001"));
}
public CommonResult handleblockHandlerException(BlockException exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
我们触发一个熔断规则,可以看到如下输出
fallback
和blockHandler
同时存在
fallback
负责处理异常,blockHandler
负责sentinel控制台配置违规。
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException", fallback = "handleFallback")
public CommonResult byResource() {
return new CommonResult(200, "按资源名称限量ok", new Payment(2020L, "SERIAL001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444, "handleException\t 服务不可用");
}
public CommonResult handleFallback(Throwable exception) {
return new CommonResult(444, "handleFallback\t 服务不可用");
}
评论 (0)