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

相关推荐
道之极万物灭5 分钟前
Go小工具合集
开发语言·后端·golang
瑞士卷@5 分钟前
MyBatis入门到精通(Mybatis学习笔记)
java·数据库·后端·mybatis
optimistic_chen30 分钟前
【Java EE进阶 --- SpringBoot】Mybatis - plus 操作数据库
数据库·spring boot·笔记·java-ee·mybatis·mybatis-plus
yuuki23323337 分钟前
【C语言】文件操作(附源码与图片)
c语言·后端
唐僧洗头爱飘柔952737 分钟前
【SpringCloud(6)】Gateway路由网关;zuul路由;gateway实现原理和架构概念;gateway工作流程;静态转发配置
spring·spring cloud·架构·gateway·请求转发·服务降级·服务雪崩
IT_陈寒40 分钟前
Python+AI实战:用LangChain构建智能问答系统的5个核心技巧
前端·人工智能·后端
无名之辈J1 小时前
系统崩溃(OOM)
后端
来旺1 小时前
互联网大厂Java面试全解析及三轮问答专项
java·数据库·spring boot·安全·缓存·微服务·面试
码农刚子1 小时前
ASP.NET Core Blazor简介和快速入门 二(组件基础)
javascript·后端
间彧1 小时前
Java ConcurrentHashMap如何合理指定初始容量
后端