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

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 内置过滤器之前

自定义异常过滤器

// 因为版面原因,省略从ExceptionFilter 抄写的大部分代码
@Activate(group = Constants.PROVIDER)
public class AyaDubboExceptionFilter implements Filter {
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        try {
            Result result = invoker.invoke(invocation);
            if (result.hasException() && GenericService.class != invoker.getInterface()) {
                try {
                    Throwable exception = result.getException();
                    // 如果是checked异常,直接抛出


                    //  项目定义的一个异常
                    if ( exception instanceof  MyCustomException) {
                        return result;
                    }

                    // 在方法签名上有声明,直接抛出
                    // 异常类和接口类在同一jar包里,直接抛出
                    // 是JDK自带的异常,直接抛出
                    // 是Dubbo本身的异常,直接抛出

                    // 否则,包装成RuntimeException抛给客户端
                    return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
                } catch (Throwable e) {
                    return result;
                }
            }
            return result;
        } catch (RuntimeException e) {
            throw e;
        }
    }
}

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

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

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

   public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
       ///省略...
       return getDefaultRpcResult(exception);
    }

    protected RpcResult getDefaultRpcResult(Result result) {
        return new RpcResult(new RuntimeException(StringUtils.toString(result.getException())));
    }

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

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

 protected RpcResult getDefaultRpcResult(Result result) {
         if ( result.getException() instanceof  MyCustomException) {
                   return result;
         }
         return super.getDefaultRpcResult(result);
    }

猜你喜欢

转载自blog.csdn.net/mz4138/article/details/81814546