原始链接:http://www.cnblogs.com/LBSer前言假设一家银行只有10名员工。
银行的业务流程分为以下四个步骤:1)客户填写申请表(5分钟); 2)工作人员审核(1分钟); 3)工作人员要求保安去金库取钱(3分钟); 4)工作人员打印账单,并将钱和账单退还给客户(1分钟)。
让我们看一下不同银行的工作方式如何影响其工作效率。
1 BIO方法每次客户来访时,工作人员都会立即收到并处理该工作,该工作人员负责上述4个完整的过程。
当客户超过10个时,其余客户需要排队等候。
让我们计算一下该银行在一小时内可以处理多少个客户?业务员处理一个客户需要10分钟(5 + 1 + 3 + 1),一个小时(60分钟)可以处理6个客户,总共10名员工,也就是说,只能处理60个客户。
可以看出,银行工作人员的工作状态还没有达到饱和。
例如,在第一步中,他们实际上正在等待。
这种工作实际上是BIO。
每次请求(客户)到来时,它都会分配给线程池并由线程(员工)进行处理。
如果超出了线程池(10)的最大限制,则将其扔入队列以等待。
2 NIO方法如何提高银行的吞吐量?想法:分而治之,分解任务,让特殊的人来负责特殊的任务。
具体来说,银行专门分配了一名职员A。
当客户到达银行时,A的工作是交出一张表格供客户填写。
每当客户填写表格时,A便将其随机分配给其余九个人。
员工完成了下一步。
让我们计算一下这种工作方式,银行在一小时内可以处理多少个客户?假设有很多客户,并且业务员A的工作已经饱和。
他不断地将填写表格的客户带到柜台进行处理。
柜台的一名职员可以在5分钟内处理一位客户,而9名员工可以在一个小时内处理一位客户:9 *(60/5)= 108。
可以看出,改变工作方法可以大大提高效率。
这种工作方式实际上是基于NIO的想法。
下图是一个非常经典的NIO插图。
mainReactor线程负责监视服务器套接字,接受新连接以及将已建立的套接字分配给subReactor。
subReactor可以是线程或线程池(通常可以将其设置为CPU内核数),负责对连接的套接字进行多路分解,读取和写入网络数据。
可以将此处的网络数据读写与客户填写表格的耗时操作进行比较。
对于特定的业务处理功能,它被扔到工作线程池中以完成任务。
可以看出,典型的NIO具有三种类型的线程,即mainReactor线程,subReactor线程和工作线程。
不同的线程会做一些专业的事情,最终每个线程都不可用,系统的吞吐量自然会上升。
3异步模式第二种工作模式是否有改进?仔细检查发现,柜台业务员在步骤3中等待了3分钟。
我们如何保持柜台业务员满负荷工作?或分而治之的思想,指派一名工作人员B负责第三步。
每当柜台工作人员完成步骤2时,都会通知工作人员B与保安人员进行通信以提取资金。
此时,柜台人员可以继续与下一位客户打交道。
员工B拿到钱后会怎么做?他将通知客户钱已经到达柜台,并要求客户再次排队。
当柜台业务员再次为客户提供服务时,他发现客户已经完成了前3个步骤,可以直接进行第4步。
我们可以计算出通过这种方法可以增加多少银行的吞吐量。
假设B员工的工作非常饱和,那么柜台上的一名员工现在可以在2分钟内处理一位客户,而8名员工在一小时内可以处理该客户:8 *(60/2)= 240。
在当今的Web服务中,通常必须通过RPC或Http调用第三方服务。
这对应于第三步。
如果此步骤花费很长时间,则异步方法将大大降低资源利用率。
Jetty Continuations实现了上述异步方法,感兴趣的学生可以尝试一下(http://wiki.eclipse.org/Jetty/Feature/Continuations)。
NIO +异步方法允许少量线程(资源)做很多事情。
这适用于许多应用程序场景,例如代理服务,api服务和持久连接服务。
这些应用程序将消耗大量机器