Dubbo基于Filter处理全局异常

背景

在服务化的过程中,基于RPC的服务调用出现异常时,往往需要异常的类进行序列化以及反序列化处理,而在开发的过程中,如果开发人员没有将异常描述类,进行开放处理,经常会出现异常类描述无法得知的问题,所以需要以及全局的补充行为,防止出现异常类不存在,导致异常信息丢失的问题

技术方案

Dubbo的Filter机制,是专门为服务提供方和服务消费方调用过程进行拦截设计的,每次远程方法执行,该拦截都会被执行。这样就为开发者提供了非常方便的扩展性,比如为dubbo接口实现ip白名单功能、监控功能等等。这里将使用fitler作为全局补充异常处理

步骤

自定义FIlter实现方法很简单,分为3个步骤:
1、自定义Filter,必须继承com.alibaba.dubbo.rpc.Filter接口
2、在resources目录下添加纯文本文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容写成 xxx=xxx.xxx.xxxFilter
3、在dubbo配置xml中添加 <dubbo:provider filter="xxxFilter" /> 或者 <dubbo:consumer filter="xxxFilter" /> 使Filter生效。

代码实现

@Activate(group = Constants.PROVIDER)
public class CommonExceptionFilter implements Filter {

    private final Logger logger;

    public CommonExceptionFilter() {        this(LoggerFactory.getLogger(CommonExceptionFilter.class));
    }
    public CommonExceptionFilter(Logger logger) {
        this.logger = logger;
    }
    private void fillInStackTrace(Throwable exception) {
        exception.setStackTrace(exception.getStackTrace());
    }
    @Override
    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();
                    //todo ApplicationException 具体的异常类
                    if (exception instanceof ApplicationException) {//若是业务异常 则直接返回
                        fillInStackTrace(exception);
                        return result;
                    }                    if (!(exception instanceof RuntimeException)
                            && (exception instanceof Exception)) {
                        return result;
                    }                    try {
                        Method method = invoker.getInterface()
                                .getMethod(invocation.getMethodName(),
                                        invocation.getParameterTypes());
                        Class<?>[] exceptionClassses = method.getExceptionTypes();
                        for (Class<?> exceptionClass : exceptionClassses) {                            if (exception.getClass().equals(exceptionClass)) {
                                return result;
                            }                        }
                    } catch (NoSuchMethodException e) {
                        return result;
                    }
                    logger.error("发现未声明的异常类型 " + RpcContext.getContext().getRemoteHost()
                                    + ". service: " + invoker.getInterface().getName() + ", method: "
                                    + invocation                                    .getMethodName()
                                    + ", exception: " + exception.getClass().getName() + ": " + exception
                                    .getMessage(),
                            exception);

                    String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
                    String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
                    if (serviceFile == null || exceptionFile == null || serviceFile                            .equals(exceptionFile)) {
                        return result;
                    }                    String className = exception.getClass().getName();
                    if (className.startsWith("java.") || className.startsWith("javax.")) {                        return result;
                    }                    if (exception instanceof RpcException) {
                        return result;
                    }                    return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
                } catch (Throwable e) {                    logger.warn("执行异常过滤失败 " + RpcContext.getContext().getRemoteHost()
                            + ". service: " + invoker.getInterface().getName() + ", method: "
                            + invocation                            .getMethodName()
                            + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
                    return result;
                }            }
            return result;
        } catch (RuntimeException e) {            logger.error("发现未声明的异常类型 " + RpcContext.getContext().getRemoteHost()
                    + ". service: " + invoker.getInterface().getName() + ", method: " + invocation
                    .getMethodName()
                    + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
            throw e;
        }    }
}

关于作者

小小鼠标垫
哼嗬哈嘿
获得点赞
文章被阅读