当前位置:首页 > 服务端 > Dubbo IO异常的捕获

Dubbo IO异常的捕获

需求

为什么要写这么一个小问题呢,可能有同学说了,发生异常后不是自动就体现到日志里面去了吗?有啥可捕获的?

想想这么一个场景:

生产环境中众多日志中发现了如下异常信息:

[New I/O worker #1][Log4j2Logger.java:73] - 
Data length too large: 1895857664, max payload: 8388608, 
channel: NettyChannel [channel=[id: 0xbe23f2b5, 
/172.31.5.38:36596 => /172.31.2.196:21880]]\n\"\

用过Dubbo的都知道,这是因为 RPC接口的返回值过大,超出了设定的响应最大值,可以通过修改 payload 参数来解决。

通过这个信息你大致可以知道是 哪两个服务 交互时发生的异常,但是无法知道具体是哪个接口、哪个方法、什么参数情况下产生的这个异常,里面也没有logId。

这就是老吕要捕获它的原因,我要把产生这个错误时对应的 logId,接口名称,方法名称,和参数值 全部记录下来,方便业务开发的同学进行优化改进。

logId在每一个业务线程中都会绑定,发生业务异常时日志中就会自动记录下 logId,开发人员可以方便的检索 分布式链路日志解决问题。但是这个IO异常是产生的IO线程上的,大家都知道在NIO架构中IO线程是所有业务线程共享的,这就意味着 IO线程上不可能绑定业务logId这个东西,所以它出来的异常中是没有logId这个东西的。

解决方案

关于Dubbo IO线程模型的先不说了,下面直接给出一个针对此问题的可行的解决方案:

由于这个IO异常的根源产生在提供者端,我一直想在提供者端捕获,最终证明不太可行(有知道的同学可以通知我下),还是要到消费者端捕获。

我分别写了2个过滤器,一个是提供者端过滤器,一个是消费者端过滤器,看里面的注释就知道怎么做了,如下:

##提供者过滤器(无法感知Duboo IO异常,这里只是为了说明问题)

public class MyProviderFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            Result result = invoker.invoke(invocation);
            if (result.hasException()) {
                //是否有异常,异常处理,这里可以感知所有的业务线程异常,但无法感知Dubbo的IO异常
            }
            return result;
        }catch (Throwable e){
            //这里也无法感知IO异常
            e.printStackTrace();
            throw e;
        }finally {
            String log = invoker.getInterface().getCanonicalName()+","+invocation.getMethodName();
            System.out.println(log+","+(System.currentTimeMillis()-startTime));
        }


    }
}

##消费者过滤器(可以感知Dubbo IO异常,但是也需要特殊处理才行)

public class MyConsumerFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            Result result = invoker.invoke(invocation);
            if (result.hasException()) {
                //是否有异常,异常处理,这里无法感知Dubbo IO异常
            }
            return result;
        }catch (Throwable e){
            //这里可以感知IO异常
            dubboRpcLog(invoker,invocation,e.getMessage());
            throw e;
        }finally {
            String log = invoker.getInterface().getCanonicalName()+","+invocation.getMethodName();
            System.out.println(log+","+(System.currentTimeMillis()-startTime));
        }


    }




    /**
     * 记录调用日志
     * @param invoker
     * @param invocation
     */
    private void dubboRpcLog(Invoker<?> invoker, Invocation invocation,String errorMsg) {


        StringBuilder message = new StringBuilder();
        message.append("dubboUrl:").append(invoker.getUrl()).append(";");
        message.append("interface:").append(invoker.getInterface().getName()).append(";");
        message.append("methodName:").append(invocation.getMethodName()).append(";");


        Class<?>[] parameterTypes = invocation.getParameterTypes();
        Object[] arguments = invocation.getArguments();


        if (parameterTypes!=null||parameterTypes.length>0) {
            message.append("arguments:");
            try {
                message.append(JSON.json(arguments));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println(message.toString());
    }
}

今天就到这里,希望对你有所帮助

Dubbo IO异常的捕获 _ JavaClub全栈架构师技术笔记

扫码加微信技术群

Dubbo IO异常的捕获 _ JavaClub全栈架构师技术笔记

作者:老吕架构
来源链接:https://blog.csdn.net/super_scan/article/details/121092559


版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/server/69201.html

标签: Dubbo异常
分享给朋友: