目录大纲:

  1. 前言
  2. 处理耗时业务的第一种方式-------handler 种加入线程池
  3. 处理耗时业务的第二种方式-------Context 中添加线程池
  4. 总结:两种方式的对比和思考

前言

熟悉 Netty 的同学都知道,不能在 Netty 中做耗时的,不可预料的操作,比如数据库,网络请求,这将会严重影响 Netty 对 Socket 的处理速度。而解决方法就是将耗时任务添加到异步线程池中。但就添加线程池这步操作来讲,可以有2种方式,而且这2种方式的区别也蛮大的。今天就好好讲一讲。

1. 处理耗时业务的第一种方式-------handler 种加入线程池

以我们之前的 Netty 的 demo 源码例子,在 channelRead 方法种进行异步:

上图中的 channelRead 方法,我们模拟了一个耗时 10 秒的操作,于是,我们将这个任务提交到了一个自定义的业务线程池中,这样,就不会阻塞 Netty 的 IO 线程。

这样操作之后,整个程序的逻辑是这样的:

解释一下上图,当 IO 线程轮询到一个 socket 事件,然后,IO 线程开始处理,当走到耗时 handler 的时候,将耗时任务交给业务线程池。当耗时任务执行完毕再执行 pipeline write 方法的时候(代码中使用的是 context 的 write 方法,上图画的是执行 pipeline 方法),会将任务这个任务交给 IO 线程。

下面是 write 方法的源码:

当判定下个 outbound 的 executor 线程不是当前线程的时候,会将当前的工作封装成 task ,然后放入 mpsc 队列中,等待 IO 任务执行完毕后执行队列中的任务。很明显,下个任务的线程肯定是 IO 线程,因为我们没有设置。

2. 处理耗时业务的第二种方式-------Context 中添加线程池

第二种方式是 Netty 建议的方式,在添加 pipeline 中的 handler 时候,添加一个线程池:

而 handler 中的代码不用做任何修改:

当我们在调用 addLast 方法添加线程池后,handler 将优先使用这个线程池,如果不添加,将使用 IO 线程。

所以,当走到 AbstractChannelHandlerContext 的 invokeChannelRead 方法的时候,executor.inEventLoop() 是不会通过的,因为当前线程是 IO 线程,Context(也就是 Handler) 的 executor 是业务线程,所以会异步执行,如下:

这个时候,后面的整个流程就变成和第一个方式一样了。

总结: 两种方式的对比和思考

有什么区别呢?第一种方式在 handler 中添加异步,可能更加的自由,比如如果需要访问数据库,那我就异步,如果不需要,就不异步,异步会拖长接口响应时间。因为需要将任务放进 mpscTask 中。如果不凑巧,IO 时间很短,task 很多,可能一个循环下来,都没时间执行整个 task,导致响应时间达不到指标。

第二种方式是 Netty 建议的,但是,这么做会将整个 handler 都交给业务线程池。不论耗时不耗时,都加入到队列里,不够灵活。

再回顾一下我们刚开始的图吧:

个人建议还是使用第一种方式,比较灵活。

Netty 源码阅读的思考------耗时业务到底该如何处理的更多相关文章

  1. Netty源码阅读(一) ServerBootstrap启动

    Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

  2. Netty源码阅读之如何将TCP的读写操作和指定线程绑定

    原文链接:http://xueliang.org/article/detail/20200712234015993 前言 在Netty的线程模型中,对于一个TCP连接的读写操作,都是由一个单线程完成的 ...

  3. netty源码阅读之UnpooledByteBufAllocator

    使用IDEA阅读源码Navigate下面的工具是个好东西 .可以帮助分析类的结构等 ByteBufAllocator主要用来生成三种ByteBuf :HeadBuffer,DirectBuffer,C ...

  4. Netty源码剖析-业务处理

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread 触发pipeline.fi ...

  5. netty(一)---服务端源码阅读

    NIO Select 知识 select 示例代码 : //创建 channel 并设置为非阻塞 ServerSocketChannel serverChannel = ServerSocketCha ...

  6. 【JDK1.8】JDK1.8集合源码阅读——ArrayList

    一.前言 在前面几篇,我们已经学习了常见了Map,下面开始阅读实现Collection接口的常见的实现类.在有了之前源码的铺垫之后,我们后面的阅读之路将会变得简单很多,因为很多Collection的结 ...

  7. netty源码分析之揭开reactor线程的面纱(二)

    如果你对netty的reactor线程不了解,建议先看下上一篇文章netty源码分析之揭开reactor线程的面纱(一),这里再把reactor中的三个步骤的图贴一下 reactor线程 我们已经了解 ...

  8. Netty源码分析(前言, 概述及目录)

    Netty源码分析(完整版) 前言 前段时间公司准备改造redis的客户端, 原生的客户端是阻塞式链接, 并且链接池初始化的链接数并不高, 高并发场景会有获取不到连接的尴尬, 所以考虑了用netty长 ...

  9. Netty 源码(一)服务端启动

    Netty 源码(一)服务端启动 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) ServerBootstap 创建时序图如 ...

随机推荐

  1. 第一天:html+JavaScript函数

    testjstry1.html   知识点1:求多组数据的和 function demo(a,b){ var sum=a+b; return sum;}var v1=demo(20,10);var v ...

  2. CxGrid鼠标移到更改颜色

    CxGrid鼠标移到更改颜色 设置表单中TcxGrid1DBTableView的Styles属性,设置Selection procedure TForm1.cxGrid1DBTableView1Mou ...

  3. caffe 教程

    Caffe是一个清晰而高效的深度学习框架,本文详细介绍了caffe的优势.架构,网络定义.各层定义,Caffe的安装与配置,解读了Caffe实现的图像分类模型AlexNet,并演示了CIFAR-10在 ...

  4. 机器学习实战-ch3-决策树

    决策树是一种新算法: 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据.缺点:可能会产生过度匹配问题. 决策树算法可用于数据类型:数值型和标称型. 决策树的核心在于 ...

  5. 一、winForm-DataGridView操作——控件绑定事件的两种方法

    在winForm窗体中绑定(注册)事件的方法有两种: 一.绑定事件 双击控件,即进入.cs的代码编辑页面,会出现 类似于“ private void 控件名称_Click(object sender, ...

  6. 【转】C#中dynamic的正确用法

    原文:http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4.0的新特性.dynamic ...

  7. Fiddler工具使用介绍三

    我们知道Fiddler是位于客户端和服务器之间的代理,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点.调试web应用.修改请求的数据,甚至可以修改 ...

  8. Linux删除目录下的文件的10种方法

    看到了一遍文章,便突发奇想的想起Linux中删除目录下的所有文件的方法:整理了几个,如有不足,还望读者不吝赐教! 删除当前目录下的文件 1.rm -f * #最经典的方法,删除当前目录下的所有类型的文 ...

  9. Oracle11g手动创建数据库方法

    Oracle11g手动创建数据库方法 参考网页http://www.th7.cn/db/Oracle/201311/36926.shtml 安装路径 我的安装路径是:E:\app\admin\prod ...

  10. Apache Roller 5.0.3 XXE漏洞分析

    下载5.0.2的版本来分析 5.0.2的war包地址 http://archive.apache.org/dist/roller/roller-5/v5.0.2/bin/roller-weblogge ...