背景:以前在channelRead中,接收到遠端消息進行解碼後直接使用了操做數據庫這種耗時較久的業務邏輯處理。致使本地netty的工做線程阻塞,會下降可用線程數。另外一個對於當前channel的心跳機制也有影響,會致使遠端機器長時間接受不到心跳信號,認爲這臺機器掛掉了。。。java
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("{} -> [客戶端信息] \n 方法名 - > {} \n 參數列表 -> {} \n " + "返回值 -> {} ", 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("{} -> [客戶端信息] \n 方法名 - > {} \n 參數列表 -> {} \n " + "返回值 -> {} ", 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鏈的整個過程是是同步的)ide