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

相关推荐
武子康1 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
舒一笑1 小时前
我的开源项目-PandaCoder迎来史诗级大更新啦
后端·程序员·intellij idea
@昵称不存在2 小时前
Flask input 和datalist结合
后端·python·flask
zhuyasen3 小时前
Go 分布式任务和定时任务太难?sasynq 让异步任务从未如此简单
后端·go
东林牧之3 小时前
Django+celery异步:拿来即用,可移植性高
后端·python·django
超浪的晨4 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
AntBlack4 小时前
从小不学好 ,影刀 + ddddocr 实现图片验证码认证自动化
后端·python·计算机视觉
Pomelo_刘金5 小时前
Clean Architecture 整洁架构:借一只闹钟讲明白「整洁架构」的来龙去脉
后端·架构·rust
双力臂4045 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
itLaity6 小时前
基于Kafka实现简单的延时队列
spring boot·分布式·kafka