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不同规则下,不同异常消息提示了。

相关推荐
leobertlan3 小时前
2025年终总结
前端·后端·程序员
面向Google编程3 小时前
从零学习Kafka:数据存储
后端·kafka
易安说AI4 小时前
Claude Opus 4.6 凌晨发布,我体验了一整晚,说说真实感受。
后端
易安说AI4 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
易安说AI4 小时前
用 Claude Code 远程分析生产日志,追踪 Claude Max 账户被封原因
后端
JH30735 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
颜酱5 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
qq_12498707538 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_8 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
瑶山8 小时前
Spring Cloud微服务搭建四、集成RocketMQ消息队列
java·spring cloud·微服务·rocketmq·dashboard