ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringCloud-Alibaba学习(十二):Sentinel异常处理

2022-07-07 22:34:19  阅读:169  来源: 互联网

标签:return String 处理 SpringCloud Alibaba println Sentinel 异常 public


异常处理

@SentinelResource注解

使用 Sentinel 时每个方法都可以看作是一个资源,但是默认只会将 Controller 的方法自动解析问资源,资源名为 uri。

对于服务层的方法就需要使用 @SentinelResource 注解手动标记为资源,并指定资源名。

对于默认解析的 uri 资源,Sentinel 在触发流控后会自行处理异常。而标记了 @SentinelResource 注解后,Sentinel 就只管抛出异常了,需要自定义异常处理器去处理异常。

@RestController
@RequestMapping("/anno")
public class AnnoResourceControoler {

    @SentinelResource(value = "annotest")
    @GetMapping("/test")
    public String test() {

        return "AnnoResource";
    }
}

image

流控异常处理

@SentinelResource 注解提供了一些参数可以处理异常

  • blockHandler:异常处理方法,方法需要与 @SentinelResource 标记方法在同一个类
  • blockHandlerClass:可以指定单独的异常处理类,定义一个静态的处理方法,配合 blockHandler 参数指定方法

blockHandler 处理

@RestController
@RequestMapping("/anno")
public class AnnoResourceControoler {

    @SentinelResource(value = "annotest", blockHandler = "handleException")
    @GetMapping("/test")
    public String test() {

        return "AnnoResource";
    }

    /**
     * 异常处理
     * 处理器方法修饰必须为 public
     * @param e 参数需要使用 BlockException,是 Sentinel 提供的异常类
     * @return 返回数据会作为 Controller 方法的返回
     */
    public String handleException(BlockException e) {
        e.printStackTrace();
        System.out.println(e.getClass());
        return "系统繁忙,稍后重试";
    }
}

请求参数可以传递给异常处理方法,有几个就添加几个参数,但是 BlockException 要放最后

    @SentinelResource(value = "annotest2", blockHandler = "handleException2")
    @GetMapping("/test2")
    public String test2(String name) {

        return "AnnoResource test2";
    }

    /**
     * 参数列表除 BlockException 外,要和资源方法保持一致
     */
    public String handleException2(String name, BlockException e) {
        System.out.println("请求参数:" + name);
        e.printStackTrace();
        System.out.println(e.getClass());
        return "系统繁忙,稍后重试";
    }

blockHandlerClass

    @SentinelResource(value = "annotest3", blockHandlerClass = BlockExceptionHandler.class, blockHandler = "handleException3")
    @GetMapping("/test3")
    public String test3(String name) {

        return "AnnoResource test3";
    }
public class BlockExceptionHandler {
    /**
     * 必须要 public 静态方法
     * 参数列表除 BlockException 外,要和资源方法保持一致
     * @param name
     * @param e
     * @return
     */
    public static String handleException3(String name, BlockException e) {
        e.printStackTrace();
        System.out.println(e.getClass());
        return "公共处理:系统繁忙,稍后重试 ";
    }
}

熔断降级异常处理

熔断降级抛出的是异常,捕获 Throwale 即可

熔断降级相关的参数:

  • fallback:指定异常处理方法,需要和资源方法同一个类
  • fallbackClass:指定异常类,配合 fallback 指定处理方法,处理方法是静态的
  • defaultFallback:

fallback

要求异常处理方法签名中除了 Throwable 参数外,其他需要与资源方法一致

@RestController
@RequestMapping("/break")
public class BreakController {

    @GetMapping("/test1")
    @SentinelResource(value = "breakTest1", fallback = "breakHandler")
    public String test1(Integer type) throws Exception{
        System.out.println("test1");
        if (type == null || type == 0) {
            System.out.println("正常接口调用");
        } else {
            if (type == 1) {
                System.out.println("慢调用");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (type == 2) {
                System.out.println("异常调用");
                throw new IllegalArgumentException("接口发生异常");
            }
        }
        return "test";
    }

    /**
     * 熔断降级异常处理
     * @param type
     * @param throwable  熔断处理器方法参数需要用 Throwable
     * @return
     */
    public String breakHandler(Integer type, Throwable throwable) throws Exception{
        System.out.println(throwable.getClass());
        if (throwable instanceof DegradeException ) {
            System.out.println("熔断降级异常处理");
            return "服务开小差,请稍后重试";
        } else {
            return "非sentinel异常";
        }
    }
}

fallbackClass

    @GetMapping("/test1")
    @SentinelResource(value = "breakTest1", fallbackClass = BreakExceptionHandler.class, fallback = "breakHandler2")
    public String test1(Integer type) throws Exception{
        if (type == 2) {
            System.out.println("异常调用");
            throw new IllegalArgumentException("接口发生异常");
        }
        return "test";
    }
public class BreakExceptionHandler {

    /**
     * 必须是静态方法
     * @param type 与资源方法参数一致
     * @param throwable 必须使用 Throwable
     * @return
     */
    public static String breakHandler2(Integer type, Throwable throwable) throws Exception{
        System.out.println(throwable.getClass());
        if (throwable instanceof DegradeException) {
            System.out.println("熔断降级异常处理");
            return "服务开小差,请稍后重试";
        } else {
            return "非sentinel异常";
        }
    }
}

统一异常处理

上述的流控异常处理和熔断降级异常处理,需要为每个资源编写并指定异常处理方法,太麻烦且冗余,且异常类型有限,可以使用 Spring 的全局异常处理。

image

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 流控规则全局异常处理
     *   资源方法签名上需要有异常抛出声明 throws Exception 细粒度的 BlockException 及子类也可以
     * @return
     */
    @ExceptionHandler(FlowException.class)
    public HttpResponse<Void> handleFlowException() {
        return HttpResponse.error("系统繁忙,请稍后重试");
    }

    /**
     * 熔断降级规则全局异常处理
     *   资源方法签名上需要有异常抛出声明 throws Exception 细粒度的 BlockException 及子类也可以
     * @return
     */
    @ExceptionHandler(DegradeException.class)
    public HttpResponse<Void> handleDegradeException() {
        return HttpResponse.error("系统开小差,请稍后重试");
    }

    /**
     * 权限规则全局异常处理
     * @return
     */
    @ExceptionHandler(AuthorityException.class)
    public HttpResponse<Void> handleAuthorityException() {
        return HttpResponse.error("没有权限访问");
    }

    /**
     * 未知异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public HttpResponse<Void> handleException(Exception e) {
        e.printStackTrace();
        return HttpResponse.error("全局异常");
    }
}

标签:return,String,处理,SpringCloud,Alibaba,println,Sentinel,异常,public
来源: https://www.cnblogs.com/liuyiyuan/p/16451892.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有