• channelRead对于耗时业务逻辑处理的优化


    channelRead对于耗时业务逻辑处理的优化

    背景:之前在channelRead中,接收到远端消息进行解码后直接使用了操作数据库这种耗时较久的业务逻辑处理。导致本地netty的工作线程阻塞,会降低可用线程数。另一个对于当前channel的心跳机制也有影响,会导致远端机器长时间接受不到心跳信号,认为这台机器挂掉了。。。

    原始代码

           public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if(msg instanceof MessageEntity)
            {
                MessageEntity messageEntity = (MessageEntity) msg;
                if (2==messageEntity.getMsgType())
                {
                    LOGGER.info("收到服务端发来的方法请求了--------------------------------------------");
                    // 转换为MethodInvokeMeta
                    MethodInvokeMeta invokeMeta = (MethodInvokeMeta) ((MessageEntity) msg).getData();
                    LOGGER.info("{} -> [客户端信息] 
     方法名  - > {} 
     参数列表  -> {} 
     " +
                                    "返回值  ->  {} ", this.getClass().getName(), invokeMeta.getMethodName(), invokeMeta.getArgs()
                            , invokeMeta.getReturnType());
                    // 具体的处理类
                    RequestDispatcher requestDispatcher = new RequestDispatcher();
                    requestDispatcher.dispatcher(ctx, invokeMeta);
                }
                else
                {
                    LOGGER.error("接受到的服务端请求无法识别");
                }
            }else
            {
                LOGGER.error("接受到的服务端请求无法识别");
            }
        }
    
    

    在channelRead中,dispatch是一个接受到远程调用请求的分发器,会根据调用参数执行本地具体的方法。其中大多数都包括耗时较久的数据库操作,因此这块代码亟需优化。

        requestDispatcher.dispatcher(ctx, invokeMeta); 
    

    解决方案

    啥都不说,先上代码,如下:

        ExecutorService executor = Executors.newFixedThreadPool(2);
    
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            //引入异步业务线程池的方式,避免长时间业务耗时业务阻塞netty本身的worker工作线程
            executor.submit(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    if(msg instanceof MessageEntity)
                    {
                        MessageEntity messageEntity = (MessageEntity) msg;
                        if (2==messageEntity.getMsgType())
                        {
                            LOGGER.info("收到服务端发来的方法请求了--------------------------------------------");
                            // 转换为MethodInvokeMeta
                            MethodInvokeMeta invokeMeta = (MethodInvokeMeta) ((MessageEntity) msg).getData();
                            LOGGER.info("{} -> [客户端信息] 
     方法名  - > {} 
     参数列表  -> {} 
     " +
                                            "返回值  ->  {} ", this.getClass().getName(), invokeMeta.getMethodName(), invokeMeta.getArgs()
                                    , invokeMeta.getReturnType());
                            // 具体的处理类
                            RequestDispatcher requestDispatcher = new RequestDispatcher();
                            requestDispatcher.dispatcher(ctx, invokeMeta);
                        }
                        else
                        {
                            LOGGER.error("接受到的服务端请求无法识别");
                        }
                    }else
                    {
                        LOGGER.error("接受到的服务端请求无法识别");
                    }
                    return null;
                }
            });
        }
    

    通过自己添加业务线程池的方式,避免阻塞worker工作线程(因为读完数据后,ChannelPipeline会触发 ChannelHandler链来处理业务逻辑,而ChannelHandler链的整个过程是是同步的)

  • 相关阅读:
    实用工具分享
    美国西储大学轴承数据解读
    CSDN去广告插件
    [教程]SPSS for Mac 安装教程
    [教程]Ubuntu 安装 Docker CE
    [教程]Windows操作系统下安装Ubuntu虚拟机
    Chrome视频解析插件
    [软件]MATLAB小波包的分解与重构
    [信号处理]奈奎斯特采样定理
    [软件]LabVIEW编程实例:如何通过TCP协议进行数据通信
  • 原文地址:https://www.cnblogs.com/falcon-fei/p/11422376.html
Copyright © 2020-2023  润新知