springboot框架项目实践应用十四(扩展sentinel错误提示)

1.引言

应用接入sentinel dashboard后,针对端点:/sentinel/grade/{userId}

1.1.配置流控规则

访问端点:http://127.0.0.1:8080/sentinel/grade/1,疯狂刷新!流控了!

注意:发生流控后,提示的消息是【Blocked by Sentinel (flow limiting)】

1.2.配置熔断规则

避免干扰,删除前面配置的流控规则,针对端点:/sentinel/grade/{userId},配置一个熔断规则

访问端点:http://127.0.0.1:8080/sentinel/grade/1,疯狂刷新!熔断了!

注意:发生熔断后,提示的消息是【Blocked by Sentinel (flow limiting)】

总结,有没有发现,不管是发生流控,还是熔断后,提示的信息都是【Blocked by Sentinel (flow limiting)】,见鬼了!到底是流控,还是熔断呢?请你告诉我!

1.3.透过现象看本质

前面通过案例,发现不管是发生流控,还是发生熔断,系统给的默认提示信息都是一样的,难以区分!那么这个提示信息是从哪里来的呢?

查看源码,我们发现sentinel在保护资源时,比如说超出了流控阈值,或者熔断阈值,都是抛出异常的处理方式进行处理,该异常是:BlockException,它有相应的规则子类异常,图示

那么当抛出BlockException异常后,是有谁来处理的呢?sentinel提供了一个处理接口

java 复制代码
public interface BlockExceptionHandler {
    void handle(HttpServletRequest var1, HttpServletResponse var2, BlockException var3) throws Exception;
}

以及一个默认的实现

java 复制代码
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
    public DefaultBlockExceptionHandler() {
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setStatus(429);
        PrintWriter out = response.getWriter();
        // 刚才傻傻分不清的提示信息,就是从这里来的了!
        out.print("Blocked by Sentinel (flow limiting)");
        out.flush();
        out.close();
    }
}

2.扩展BlockExceptionHandler

理解底层处理机制后,解决问题就非常简单了!我们只需要扩展BlockExceptionHandler接口,替换默认实现即可。来试一下吧!

2.1.封装消息SentinelMsg

java 复制代码
@Data
public class SentinelMsg {

    private int status;
    private String msg;
}

2.2.扩展BlockExceptionHandler

java 复制代码
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    /**
     * 重写handle方法
     * @param request
     * @param response
     * @param e
     * @throws Exception
     */
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       BlockException e) throws Exception {

        // 1.状态码,以及提示消息
        int status = HttpStatus.INTERNAL_SERVER_ERROR.value();
        String errorMsg = "sentinel 未知异常!";

        // 2.判断处理异常
        if(e instanceof FlowException){
            status = HttpStatus.TOO_MANY_REQUESTS.value();
            errorMsg = "error,限流了!";
        }else if(e instanceof DegradeException){
            errorMsg = "error,降级了!";
        }else if(e instanceof ParamFlowException){
            status = HttpStatus.TOO_MANY_REQUESTS.value();
            errorMsg = "error,热点参数限流了!";
        }else if(e instanceof AuthorityException){
            errorMsg = "error,没有访问权限!";
        }else if(e instanceof SystemBlockException){
            errorMsg = "error,系统资源不够了!";
        }

        // 3.设置响应
        response.setStatus(status);
        response.setContentType("application/json;charset=utf-8");
        SentinelMsg sentinelMsg = new SentinelMsg();
        sentinelMsg.setStatus(status);
        sentinelMsg.setMsg(errorMsg);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(response.getOutputStream(),sentinelMsg);
    }
}

3.测试效果

访问端点:http://127.0.0.1:8080/sentinel/grade/1,测试流控,提示消息

shell 复制代码
{"status":429,"msg":"error,限流了!"}

访问端点:http://127.0.0.1:8080/sentinel/grade/1,测试熔断,提示消息

shell 复制代码
{"status":500,"msg":"error,降级了!"}

这样一来,就实现了sentinel不同规则下,不同异常消息提示了。

相关推荐
花月C5 分钟前
Mysql-定时删除数据库中的验证码
数据库·后端·mysql·spring
XMYX-05 小时前
Spring Boot + Prometheus 实现应用监控(基于 Actuator 和 Micrometer)
spring boot·后端·prometheus
记得开心一点嘛7 小时前
使用MinIO搭建自己的分布式文件存储
分布式·spring cloud·minio
@yanyu6667 小时前
springboot实现查询学生
java·spring boot·后端
酷爱码8 小时前
Spring Boot项目中JSON解析库的深度解析与应用实践
spring boot·后端·json
AI小智8 小时前
Google刀刃向内,开源“深度研究Agent”:Gemini 2.5 + LangGraph 打造搜索终结者!
后端
java干货9 小时前
虚拟线程与消息队列:Spring Boot 3.5 中异步架构的演进与选择
spring boot·后端·架构
一只叫煤球的猫9 小时前
MySQL 8.0 SQL优化黑科技,面试官都不一定知道!
后端·sql·mysql
写bug写bug10 小时前
如何正确地对接口进行防御式编程
java·后端·代码规范