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

相关推荐
我不只是切图仔18 分钟前
我只是想给网站加个注册验证码,咋就那么难!
前端·后端
专注VB编程开发20年18 分钟前
CSS 的命名方式像是 PowerShell 的动词-名词结构,缺乏面向对象的层级关系
开发语言·后端·rust
野犬寒鸦20 分钟前
力扣hot100:相交链表与反转链表详细思路讲解(160,206)
java·数据结构·后端·算法·leetcode
爱吃烤鸡翅的酸菜鱼40 分钟前
【Spring】原理:Bean的作用域与生命周期
后端·spring
JohnYan40 分钟前
工作笔记 - 微信消息发送和处理
javascript·后端·微信
该用户已不存在43 分钟前
macOS是开发的终极进化版吗?
前端·后端
计算机毕业设计木哥1 小时前
计算机毕设选题:基于Python+Django的B站数据分析系统的设计与实现【源码+文档+调试】
java·开发语言·后端·python·spark·django·课程设计
歪歪1001 小时前
qt creator新手入门以及结合sql server数据库开发
c语言·开发语言·后端·qt·数据库开发
布列瑟农的星空1 小时前
大话设计模式——观察者模式和发布/订阅模式的区别
前端·后端·架构
Moonbit1 小时前
月报Vol.03: 新增Bitstring pattern支持,构造器模式匹配增强
后端·算法·github