3种Sentinel自定义异常,你用过几种?

简介: 3种Sentinel自定义异常,你用过几种?

Spring Cloud Alibaba Sentinel 是目前主流并开源的流量控制和系统保护组件,它提供了强大的限流、熔断、热点限流、授权限流和系统保护及监控等功能。使用它可以轻松的保护我们微服务,在高并发环境下的正常运行。

那么,当程序触发了限流和熔断规则时,如何自定义返回的异常信息呢?这是我们接下来要解决的问题。

0.概述

Spring Cloud Alibaba Sentinel 有以下 3 种自定义异常的实现方式:

  1. 自定义局部异常
  2. 自定义(Sentinel)全局异常
  3. 自定义系统异常

以上这 3 种实现方式,都可以重新定义 Sentinel 的异常返回信息,它们的具体实现如下。

1.自定义局部异常

自定义局部异常是在使用 @SentinelResource 注解时,直接定义的 blockHandler 异常方法,如下代码所示:

@SentinelResource(value = "/user/getuser",
            blockHandler = "myBlockHandler")
@RequestMapping("getuser")
public String getUser(Integer uid) {
   
    return "User:" + uid;
}

/**
 * 定义限流/熔断等异常
 */
public String myBlockHandler(Integer uid, BlockException e) {
   
    String msg = "未知异常";
    if (e instanceof FlowException) {
   
        msg = "请求被限流了";
    } else if (e instanceof ParamFlowException) {
   
        msg = "请求被热点参数限流";
    } else if (e instanceof DegradeException) {
   
        msg = "请求被降级了";
    } else if (e instanceof AuthorityException) {
   
        msg = "没有权限访问";
    }
    return msg;
}

注意事项

在定义 blockHandler 方法时,需要注意以下 3 个问题:

  1. 自定义的 blockHandler 方法的返回值,必须要和原方法(使用 @SentinelResource 注解修饰的方法)的返回值保持一致。
  2. 自定义的 blockHandler 方法的参数必须和原方法参数保持一致。
  3. 自定义的 blockHandler 方法的方法参数中必须包含 BlockException 参数。

如果不满足以上事项中的任何一项,那么就不能正常匹配到自定义的 blockHandler 方法,并且程序也会报错。

2.自定义全局异常

自定义 Sentinel 全局异常需要实现 BlockExceptionHandler 类,并重写 handle 方法,如下代码所示:

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
   
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
   
        String msg = "未知异常";
        int status = HttpStatus.TOO_MANY_REQUESTS.value();
        if (e instanceof FlowException) {
   
            msg = "请求被限流了";
        } else if (e instanceof ParamFlowException) {
   
            msg = "请求被热点参数限流";
        } else if (e instanceof DegradeException) {
   
            msg = "请求被降级了";
        } else if (e instanceof AuthorityException) {
   
            msg = "没有权限访问";
            status = HttpStatus.UNAUTHORIZED.value();
        }
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status);
        response.getWriter().println("{\"msg\": " + msg + ", \"code\": " + status + "}");
    }
}

自定义 Sentinel 全局异常是在执行 Sentinel 控制台设置的限流和熔断异常时,执行的全局自定义异常方法。

但是,如果是程序中出现的 Sentinel 报错信息,例如使用热点限流时,因为要配合使用 @SentinelResource 注解时,此时只自定义了 value 属性,未定义局部 blockHandler 方法,此时系统就会报错,但这个时候并不会执行 Sentinel 全局自定义异常,而是程序报错,此时就需要使用系统自定义异常来重新定义异常信息了。

3.自定义系统异常

自定义系统异常需要新建一个异常类,并且使用 @RestControllerAdvice 注解修饰此类,并配合 @ExceptionHandler 注解来完成全局系统异常的获取和定义,具体实现代码如下:

import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;


@RestControllerAdvice
public class CustomExceptionHandler {
   

    /**
     * 限流全局异常
     */
    @ExceptionHandler(FlowException.class)
    public Map handlerFlowException(){
   
        return new HashMap(){
   {
   
            put("code", HttpStatus.TOO_MANY_REQUESTS.value());
            put("msg", "被限流");
        }};
    }

    /**
     * 熔断全局异常
     */
    @ExceptionHandler(DegradeException.class)
    public Map handlerDegradeException(){
   
        return new HashMap(){
   {
   
            put("code", HttpStatus.TOO_MANY_REQUESTS.value());
            put("msg", "被熔断");
        }};
    }

    /**
     * 热点限流异常
     */
    @ExceptionHandler(ParamFlowException.class)
    public Map handlerparamFlowException(){
   
        return new HashMap(){
   {
   
            put("code", HttpStatus.TOO_MANY_REQUESTS.value());
            put("msg", "热点限流");
        }};
    }

    /**
     *  Sentinel 权限拦截全局异常
     */
    @ExceptionHandler(AuthorityException.class)
    @ResponseBody
    public Map handlerAuthorityException(){
   
        return new HashMap(){
   {
   
            put("code", HttpStatus.UNAUTHORIZED.value());
            put("msg", "暂无权限");
        }};
    }
}

此时,只要是系统中出现的 Sentinel 报错信息,都会被此方法所捕获,并通过自定义的代码完成自定义异常信息的返回。

小结

Sentinel 有 3 种自定义异常的实现:自定义局部异常、自定义(Sentinel)全局异常、自定义系统异常。自定义局部异常作用范围比较小,需要给每个资源单独设置才行;而自定义全局异常作用范围比较大,但如果是程序报错,也不会执行其方法,所以需要配合系统异常同时来完成自定义异常的返回。

PS:如果这 3 种自定义异常同时存在,那么它的执行优先级是:自定义局部异常 > 自定义全局异常 > 自定义系统异常。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关文章
|
开发框架 Sentinel 微服务
SpringCloud微服务实战——搭建企业级开发框架(十六):集成Sentinel高可用流量管理框架【自定义返回消息】
Sentinel限流之后,默认的响应消息为Blocked by Sentinel (flow limiting),对于系统整体功能提示来说并不统一,参考我们前面设置的统一响应及异常处理方式,返回相同的格式的消息。 1、在自定义Sentinel返回消息之前,需要调整一下代码结构,因为这里要用到统一返回异常的格式,考虑到后期可能的使用问题,
324 57
SpringCloud微服务实战——搭建企业级开发框架(十六):集成Sentinel高可用流量管理框架【自定义返回消息】
|
2月前
|
Java UED Sentinel
微服务守护神:Spring Cloud Sentinel,让你的系统在流量洪峰中稳如磐石!
【8月更文挑战第29天】Spring Cloud Sentinel结合了阿里巴巴Sentinel的流控、降级、熔断和热点规则等特性,为微服务架构下的应用提供了一套完整的流量控制解决方案。它能够有效应对突发流量,保护服务稳定性,避免雪崩效应,确保系统在高并发下健康运行。通过简单的配置和注解即可实现高效流量控制,适用于高并发场景、依赖服务不稳定及资源保护等多种情况,显著提升系统健壮性和用户体验。
59 1
|
4月前
|
监控 Java Sentinel
使用Sentinel进行服务调用的熔断和限流管理(SpringCloud2023实战)
Sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
121 3
|
19天前
|
监控 Java Nacos
SpringCloud基础5——微服务保护、Sentinel
sentinel、雪崩问题、流量控制、隔离和降级、授权规则、规则持久化
SpringCloud基础5——微服务保护、Sentinel
|
3月前
|
监控 Java 应用服务中间件
SpringCloud面试之流量控制组件Sentinel详解
SpringCloud面试之流量控制组件Sentinel详解
171 0
|
3月前
|
监控 Dubbo 应用服务中间件
通用快照方案问题之Sentinel与SpringCloud和Dubbo的整合如何解决
通用快照方案问题之Sentinel与SpringCloud和Dubbo的整合如何解决
39 0
|
4月前
|
Java 开发者 Sentinel
Spring Cloud系列——使用Sentinel进行微服务保护
Spring Cloud系列——使用Sentinel进行微服务保护
57 5
|
4月前
|
监控 Java API
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
89 0
深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南
|
4月前
|
自然语言处理 监控 开发者
springCloud之Sentinel流量路由、流量控制、流量整形、熔断降级
springCloud之Sentinel流量路由、流量控制、流量整形、熔断降级
|
5月前
|
Java 数据安全/隐私保护 Sentinel
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流
微服务学习 | Spring Cloud 中使用 Sentinel 实现服务限流