异常处理
默认情况下,Sentinel 会抛出 BlockException 异常,如果希望自定义异常,则可以使用 @SentinelResource 注解的 blockHandler 属性。
1、自定义异常处理 BlockExceptionHandler
自定义异常处理类实现 BlockExceptionHandler 接口,并重写 handleException 方法,然后将其注册到 Spring 容器中。
基本概念:当 Sentinel 的规则(如流控规则、降级规则等)被触发时,会抛出 BlockException 异常。通过实现 BlockExceptionHandler 接口,可以自定义这些异常的处理逻辑
代码例子 🚀
@Component
public class CustomBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
// 根据不同的规则类型返回不同的提示信息
String msg = "请求被限流";
int status = 429;
if (e instanceof FlowException) {
msg = "接口被限流了";
status = 429;
} else if (e instanceof DegradeException) {
msg = "接口被降级了";
status = 429;
} else if (e instanceof ParamFlowException) {
msg = "热点参数限流";
status = 429;
} else if (e instanceof AuthorityException) {
msg = "授权规则不通过";
status = 401;
} else if (e instanceof SystemBlockException) {
msg = "系统规则(负载/...)不满足要求";
status = 429;
}
// 返回JSON格式的错误信息
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
Map<String, Object> result = new HashMap<>();
result.put("code", status);
result.put("message", msg);
result.put("timestamp", System.currentTimeMillis());
response.getWriter().write(new ObjectMapper().writeValueAsString(result));
}
}
2、自定义异常处理 blockHandler
使用 @SentinelResource 注解的 blockHandler 属性,指定自定义的异常处理方法。🎁
基本概念:Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。【兜底处理😎】
注意⚡⚡⚡:blockHandler 函数的参数列表需要和原方法一致,或者可以额外多一个 BlockException 参数用于接收异常。
代码例子 🚀
// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
throw new RuntimeException("getUserById command failed");
}
// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
return new User("admin");
}
3、特别注意🔕
BlockExceptionHandler 和 blockHandler 的关系:
注意🚓: 如果方法上使用了 @SentinelResource 并指定了 blockHandler,会优先使用该处理方法,而不会走到 BlockExceptionHandler。