dubbo 异常处理以及自定义异常

我会带着你远行 2022-05-16 09:15 478阅读 0赞

dubbo 抛出异常分析

在进行dubbo调用时,会抛出哪些异常? 为什么有时候是RpcException,有时候又是用户抛出的异常

dubbox2.8.4 中com.alibaba.dubbo.rpc.filter.ExceptionFilter 的注释得知:

  1. 如果是checked异常,直接抛出 ! (exception instanceof RuntimeException) && (exception instanceof Exception)
  2. 在方法签名上有声明,直接抛出 throws MyCustomException
  3. 异常类和接口类在同一jar包里,直接抛出
  4. 是JDK自带的异常,直接抛出(className.startsWith("java.") || className.startsWith("javax."))
  5. 是Dubbo本身的异常,直接抛出(RpcException)
  6. 其他异常通过RpcException
    作者都已经贴出代码和注释了. 这还有什么好分析的呢?

这里针对一个场景,对ExceptionFilter类提出一点建议。

场景

provider A 希望服务A,服务B,服务C抛出 MyCustomException 的时候, consumer A 都能获得的是 MyCustomException 而不是 RpcException

提供者 (provider A) + (provider model) + (common model)
消费者 (consumer A) + (provider model) + (common model)

  1. provider model 存放接口
  2. common model 存放异常类

这样就无法做到 ExceptionFilter 定义的第3条:异常类和接口类在同一jar包里,直接抛出

这时,就得覆盖 ExceptionFilter 相关的代码才可以。

实现

  1. 新建 META-INF/dubbo/com.alibaba.dubbo.rpc.Filter 文本文件(文件无后缀), 定义内容ayaDubboExceptionFilter=com.aya.AyaDubboExceptionExtendsFilter
  2. 在dubbo-provider.xml中定义<dubbo:provider filter="ayaDubboExceptionFilter,-exception" /> (ayaDubboExceptionFilter必须和Filter配置文件的key一致)

说明: ExceptionFilter 的key 是exception. 要用-exception删除默认的过滤器

  1. 自定义的过滤器定义在dubbo:provider>filter属性时, 在 dubbo 内置过滤器之后.
  2. 未在 dubbo:provider>filter 定义属性时,在 dubbo 内置过滤器之前

自定义异常过滤器

  1. // 因为版面原因,省略从ExceptionFilter 抄写的大部分代码
  2. @Activate(group = Constants.PROVIDER)
  3. public class AyaDubboExceptionFilter implements Filter {
  4. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
  5. try {
  6. Result result = invoker.invoke(invocation);
  7. if (result.hasException() && GenericService.class != invoker.getInterface()) {
  8. try {
  9. Throwable exception = result.getException();
  10. // 如果是checked异常,直接抛出
  11. // 项目定义的一个异常
  12. if ( exception instanceof MyCustomException) {
  13. return result;
  14. }
  15. // 在方法签名上有声明,直接抛出
  16. // 异常类和接口类在同一jar包里,直接抛出
  17. // 是JDK自带的异常,直接抛出
  18. // 是Dubbo本身的异常,直接抛出
  19. // 否则,包装成RuntimeException抛给客户端
  20. return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
  21. } catch (Throwable e) {
  22. return result;
  23. }
  24. }
  25. return result;
  26. } catch (RuntimeException e) {
  27. throw e;
  28. }
  29. }
  30. }

这样就已经替换了原先的ExceptionFilter相关的处理。

但是这样解决的方案真的是太糟糕了. 我居然新建了一个类,把原先的代码抄了一份。

假设原作者能把最后面一句 return new RpcResult(new RuntimeException(StringUtils.toString(exception))); 换成一个可以继承的那就非常好了

  1. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
  2. ///省略...
  3. return getDefaultRpcResult(exception);
  4. }
  5. protected RpcResult getDefaultRpcResult(Result result) {
  6. return new RpcResult(new RuntimeException(StringUtils.toString(result.getException())));
  7. }

目前dubbox2.8.4 和 dubbo2.6.1 都存在这样的问题,可以优化

假设原作者按照上述方式修改.我们只要按照下面的方式,就可以自行处理默认的异常了:

  1. protected RpcResult getDefaultRpcResult(Result result) {
  2. if ( result.getException() instanceof MyCustomException) {
  3. return result;
  4. }
  5. return super.getDefaultRpcResult(result);
  6. }

发表评论

表情:
评论列表 (有 0 条评论,478人围观)

还没有评论,来说两句吧...

相关阅读

    相关 dubbo 定义异常

    前言 在很多公司,使用dubbo做微服务治理也是很常见的一种方式,简单来说,就是服务提供者一方将服务注册并发布到注册中心,消费者订阅服务,然后像调用本地接口一样; 但是