资讯专栏INFORMATION COLUMN

一个故事讲清楚NIO

LeviDing / 2793人阅读

摘要:尽管异步能提高系统吞吐量,但其并不能让一个请求的等待时间下降,相反可能会增加等待时间。

假设某银行只有10个职员。该银行的业务流程分为以下4个步骤:
1) 顾客填申请表(5分钟);
2) 职员审核(1分钟);
3) 职员叫保安去金库取钱(3分钟);
4) 职员打印票据,并将钱和票据返回给顾客(1分钟)。
  我们看看银行不同的工作方式对其工作效率到底有何影响。
1 BIO方式
  每来一个顾客,马上由一位职员来接待处理,并且这个职员需要负责以上4个完整流程。当超过10个顾客时,剩余的顾客需要排队等候。
  我们算算这个银行一个小时到底能处理多少顾客?一个职员处理一个顾客需要10分钟(5+1+3+1)时间,一个小时(60分钟)能处理6个顾客,一共10个职员,那就是只能处理60个顾客。
  可以看到银行职员的工作状态并不饱和,比如在第1步,其实是处于等待中。
  这种工作其实就是BIO,每次来一个请求(顾客),就分配到线程池中由一个线程(职员)处理,如果超出了线程池的最大上限(10个),就扔到队列等待 。
2 NIO方式
  如何提高银行的吞吐量呢?
  思路:分而治之,将任务拆分开来,由专门的人负责专门的任务。
  具体来讲,银行专门指派一名职员A,A的工作就是每当有顾客到银行,他就递上表格让顾客填写,每当有顾客填好表后,A就将其随机指派给剩余的9名职员完成后续步骤。
  我们计算下这种工作方式下银行一个小时到底能处理多少顾客?
  假设顾客非常多,职员A的工作处于饱和中,他不断的将填好表的顾客带到柜台处理,柜台一个职员5分钟能处理完一个顾客,一个小时9名职员能处理:9*(60/5)=108。
  可见工作方式的转变能带来效率的极大提升。

  这种工作方式其实就NIO的思路。下图是非常经典的NIO说明图,mainReactor线程负责监听server socket,accept新连接,并将建立的socket分派给subReactor;subReactor可以是一个线程,也可以是线程池(一般可以设置为CPU核数),负责多路分离已连接的socket,读写网络数据,这里的读写网络数据可类比顾客填表这一耗时动作,对具体的业务处理功能,其扔给worker线程池完成。

  可以看到典型NIO有三类线程,分别是mainReactor线程、subReactor线程、work线程。不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。

3 异步方式
  第二种工作方式有没有什么可以提高的地方呢?
  仔细查看可发现第3步骤这3分钟柜台职员是在等待中度过的,那怎么能让柜台职员保持满负荷呢?
  还是分而治之的思路,指派1个职员B来专门负责第3步骤。每当柜台员工完成第2步时,就通知职员B来负责与保安沟通取钱。这时候柜台员工可以继续处理下一个顾客。当职员B拿到钱之后,他会怎么办呢?他会通知顾客钱已经到柜台了,让顾客重新排队处理,当柜台职员再次服务该顾客时,发现该顾客前3步已经完成,直接执行第4步即可。
  我们可以算算通过这种方法,银行的吞吐量能提高到多少。
  假设职员B的工作非常饱和,柜台一个职员现在2分钟能处理完一个顾客,一个小时8名职员能处理:8*(60/2)=240。
  在当今web服务中,经常需要通过RPC或者Http等方式调用第三方服务,这里对应的就是第3步,如果这步耗时较长,通过异步方式将能极大降低资源使用率。
  jetty Continuations 就实现了上述异步方式(http://wiki.eclipse.org/Jetty...)。
  NIO+异步的方式能让少量的线程(资源)做大量的事情,这适用于很多应用场景,比如代理服务、api服务、长连接服务等等,这些应用如果用同步方式将耗费大量机器资源。尽管NIO+异步能提高系统吞吐量,但其并不能让一个请求的等待时间下降,相反可能会增加等待时间。
4 小结
  总结就一句:“分而治之,将任务拆分开来,由专门的人负责专门的任务”,这不仅在计算机领域生效,在整个社会领域都生效。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71734.html

相关文章

  • 讲清之javascript作用域

    摘要:并且作用域链也确定了在当前上下文中查找标识符后返回的值。为了具象化分析问题,我们可以假设作用域链是一个数组,数组成员有一系列变量对象组成。注意,所有作用域链的最末端都为全局变量对象。所以作用域作用域链都是在当前运行环境内代码执行前就确定了。 什么是作用域(Scope)? 作用域产生于程序源代码中定义变量的区域,在程序编码阶段就确定了。javascript 中分为全局作用域(Global...

    whidy 评论0 收藏0
  • 讲清之javascript作用域

    摘要:并且作用域链也确定了在当前上下文中查找标识符后返回的值。为了具象化分析问题,我们可以假设作用域链是一个数组,数组成员有一系列变量对象组成。注意,所有作用域链的最末端都为全局变量对象。所以作用域作用域链都是在当前运行环境内代码执行前就确定了。 什么是作用域(Scope)? 作用域产生于程序源代码中定义变量的区域,在程序编码阶段就确定了。javascript 中分为全局作用域(Global...

    jonh_felix 评论0 收藏0
  • 如何准备校招技术面试

    摘要:网易跨境电商考拉海购在线笔试现场技术面面。如何看待校招面试招聘,对公司而言,是寻找劳动力对员工而言,是寻找未来的同事。 如何准备校招技术面试 标签 : 面试 [TOC] 2017 年互联网校招已近尾声,作为一个非 CS 专业的应届生,零 ACM 经验、零期刊论文发表,我通过自己的努力和准备,从找实习到校招一路运气不错,面试全部通过,谨以此文记录我的校招感悟。 写在前面 写作动机 ...

    MkkHou 评论0 收藏0
  • Conflux吐槽君:IOTA物联网电磁炉-让PoW的耗电没有遗憾

    摘要:任何人或物联网设备想发起交易,只需要引用其他两个交易就可以了。只要好人的交易总数足够多,它就是安全的。要知道,应用场景是物联网设备,物联网设备跑真是天才的想法啊。不仅如此,这个电磁炉还能提高烹饪的安全系数。 鉴于有不少小伙伴反映,觉得区块链技术圈乱象横生,鱼龙混杂,导致大家很难去辨识哪些是真正的技术。甚至有些人,打着说技术的名号,其实自己本身都没弄懂弄明白,只是懂个皮毛,就开始拿着各种...

    JouyPub 评论0 收藏0
  • Conflux吐槽君:IOTA物联网电磁炉-让PoW的耗电没有遗憾

    摘要:任何人或物联网设备想发起交易,只需要引用其他两个交易就可以了。只要好人的交易总数足够多,它就是安全的。要知道,应用场景是物联网设备,物联网设备跑真是天才的想法啊。不仅如此,这个电磁炉还能提高烹饪的安全系数。 鉴于有不少小伙伴反映,觉得区块链技术圈乱象横生,鱼龙混杂,导致大家很难去辨识哪些是真正的技术。甚至有些人,打着说技术的名号,其实自己本身都没弄懂弄明白,只是懂个皮毛,就开始拿着各种...

    seasonley 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<