Sentinel注解@SentinelResource详解
熔断
针对访问超过限制【sentinel中配置的限制】的资源,通过java代码配置,返回一个自定义的结果,需要用到 @SentinelResource
注解的 blockHandlerClass
和 blockHandler
属性。
blockHandlerClass:自定义处理类
blockHandler:自定义处理方法,填方法名即可
配置方式
// 接口配置
@GetMapping(path = {"/testD"})
@SentinelResource(value = "test_d",blockHandlerClass = HandlerConfig.class,blockHandler = "errorMsg")
public Map testD(@RequestParam("p1") String p1){
Map result = new HashMap<String,Object>();
result.put("sentinel_server:","testD");
return result;
}
// 自定义限流后的返回结果类
public class HandlerConfig {
public static Map errorMsg(String p1,BlockException blockException){
Map result = new HashMap<String,Object>();
result.put("error:","400");
result.put("msgA","接口限流");
result.put("p1",p1);
return result;
}
}
⚠️注意
testD方法
和自定义返回结果处理方法errorMsg
必须返回统一的数据类型- 如果
testD方法
中携带参数,那么自定义返回结果处理方法errorMsg
必须定义类型,顺序一样的参数自定义返回结果处理方法errorMsg
必须使用static
修饰自定义返回结果处理方法errorMsg
的参数必须携带BlockException
,且必须作为最后一个参数。
内部错误
对于方法内部出现的异常,sentinel也是可以处理的,通过java代码配置,不返回一个类似如下图的报错,而是返回一个自定义的结果。需要用到 @SentinelResource
注解的 fallbackClass
和 fallback
属性。
📓 对于内部异常的处理,即使不在sentinel中配置,也可以正常执行。
fallbackClass:自定义处理类
fallback:自定义处理方法,填方法名即可
配置方式
// 接口配置
@GetMapping(path = {"/testD"})
@SentinelResource(value = "test_d",fallbackClass = FallbackConfig.class, fallback="handlerException")
public Map testD(@RequestParam("p1") String p1){
int i = 10/0;// 这里一定会触发异常
Map result = new HashMap<String,Object>();
return result;
}
// 自定义的对方法内部产生的异常返回我们自定义的结果处理类
@Slf4j
public class FallbackConfig {
public static Map handlerException(String p1){
Map result = new HashMap<String,Object>();
result.put("error:","400内部错误");
result.put("p1",p1);
return result;
}
}
⚠️注意
testD方法
和自定义返回结果处理方法handlerException
必须返回统一的数据类型- 如果
testD方法
中携带参数,那么自定义返回结果处理方法handlerException
必须定义类型和参数名以及顺序一样的参数自定义返回结果处理方法handlerException
必须使用static
修饰
内部错误和熔断同时存在的情况
那么如果说一个web接口既存在发生内部错误的可能,也需要超阈熔断。那么这两个配置,是否可以同时配置呢?直接说答案:可以!在未超阈的前提下,直接进入web接口方法中,如果方法执行出现内部错误,走fallback
,熔断后走HandlerConfig
,根本就不到fallback
这一步,直到时间窗口过去进入新的时间窗口。
开发者自定义忽略异常
绝大多数开发环境中,以上两种配置方式已经足够使用;不过在一些特殊的情况下,开发者不希望sentinel对某些异常直接以自定义fallback方法
的形式返回,而是直接返回异常本身,这就需要另一个属性exceptionsToIgnore
,它所包含的异常是不被sentinel的fallback管理的,也就是说一旦发生它所定义的异常,程序将不会再走自定义的fallback方法
。
@GetMapping(path = {"/testD"})
@SentinelResource(value = "test_d",
blockHandlerClass = HandlerConfig.class,blockHandler = "errorMsg",
fallbackClass = FallbackConfig.class, fallback="fallback",
exceptionsToIgnore = {IllegalArgumentException.class})
public Map testD(@RequestParam("p1") String p1){
if ( p1.equals("admin")){
// 非法参数异常被exceptionsToIgnore属性包含,所以不会走fallback方法,而是直接返回异常
throw new IllegalArgumentException("非法参数异常-admin不能用于申请");
} else if ( p1.isEmpty() ) {
// 空指针异常并未被exceptionsToIgnore属性包含,所以最后还是要走fallback方法
throw new NullPointerException("p1不能为空");
}
Map result = new HashMap<String,Object>();
result.put("sentinel_server:","testD");
result.put("p1:",p1);
return result;
}
演示效果如下