前面两节,我们分别看了BIO和NIO的两种模式Tomcat的实现方式。

BIO的方式,就是传统的一线程,一请求的模式,也就是说,当同时又1000个请求过来,如果Tomcat设置了最大Accept线程数为500,那么第一批的500个线程直接进入线程池中进行执行,而其余500个根据Accept的限制的数量在服务器端的操作系统的内核位置的socket缓冲区进行阻塞,一直到前面500个线程处理完了之后,Acceptor组件再逐步的放进来。

分析一下,这种模式的BIO的好处,可以让一个请求在cpu轮转时间片切换中最大限度的执行,如果业务请求不是很长时间的事务处理,通常在一个时间片内肯定能做完当前的请求,这样的效率算是相当的高了,因为其减少了最耗时也是最头疼的线程上下文切换;
1.但是,如果事务执行比较长的时间,例如等待一个IO数据库的操作,那么这个工作线程就会根据cpu轮转不断的进行切换,因为请求数在大并发中很多,所以不得不设置一个很高的Accept线程数,那么从cpu的耗费的资源上来看,甚至有70%的时间浪费在线程切换中,而没有真正的时间去做请求处理和业务,这是第一个问题。
2.其次,BIO每一次链接的建立和释放都需要重新来过一遍,例如一个socket进来之后,通常会对其SocketOptions的属性进行设置,包括各种Connector中配置都要与其进行一一对应,加上前面说的socket的建立,很多请求通道的资源的初始化都得重新创建,得不到复用,这个是第二个问题。
3.最后,BIO方式网络IO的阻塞等待是会让Accept线程工作效率降低很多的。
所以,基于这3个问题,特别是最后一个问题,引出了NIO的模型。

NIO的架构分为三个线程池,这里再次梳理一下:
1.Acceptor专门接socket请求,当发现又请求进来后,基于Tomcat配置的SocketOptions和一些属性的设置完毕,包装成SocketChannel,也就是NIO的socket通道抽象,塞入PollerEvent直接扔到队列当中;
2.Poller线程从队列中挨个获取PollerEvent,调用Poller线程自己持有的selector选择器,注册SocketChannel到当前的selector选择器中,然后进行selectKey的工作,这样Acceptor传递过来的SocketChannel中感兴趣的事件,就会被轮询出来,当接收事件接收之后,需要注册OP_READ事件或者OP_WRITE事件,当OP_READ事件或者OP_WRITE事件发生时,开始调用工作线程池;
3.工作线程池就是SocketProcessor,这个就是具体的工作线程,SocketProcessor的任务就是Poller线程从SocketChannel通道中轮询出来的数据包,进行解析,传递给后端的handler进行http的解析,解析出来的Request,Reponse对象,,直接调用CoyoteAdapter传递到后端的容器,通过Mapper,映射到对应的业务Servlet中。可以看到,从SocketProcessor一直到最终的业务Servlet实现,这些都是一个线程,这个线程就是工作线程。

对比Tomcat的BIO的架构,因为没有selector轮询的操作,所以并没有Poller线程,BIO中的Acceptor线程的作用依然是对socket简单的处理和属性包装,然后将socket直接扔到工作线程中来。NIO相当于是多了一个线程池,从流程上来讲,应该是多了一道手续,但是通过NIO本身基于事件触发的机制造成,Acceptor线程没必要设置的过多,这样从线程的数量上来看,大大的减少线程切换的频率,其次基于事件进行触发,将Acceptor线程执行效率中的网络IO延迟降低到最低,大大提升了Acceptor线程的执行效率。从这两点上来看,Tomcat的NIO在前面分析的BIO的三个问题中第一个问题,和第三个问题都有所改善,特别是第三个问题,全面进行了升级。

但是,对于BIO中的第一个问题,由后端事务时间过长导致工作线程池一直在运行,并且运行在一个高峰的数值,不断的进行切换,这种问题,NIO通道也没办法进行处理,这个是由业务来决定的,NIO只能保证降低的是Acceptor线程线程数,对业务帮助也是无能为力的,如果要提升这部分的效率,那就需要应用进行修改,优化JDBC和数据库,或者将业务切段来做,让事务时间尽量控制在一个可控的范畴之内。

对于第二个问题,无论是单纯的NIO和BIO通道都没有办法进行解决,但是HTTP协议中对链接的复用进行更新,在HTTP1.1中,这个keepalive是加到http请求头中的:
Keep-Alive: timeout=5, max=100 
timeout:过期时间5秒(对应httpd.conf里的参数是:KeepAliveTimeout);
max是最多能承受一百次请求的共享复用,就是在timeout时间内又有新的连接过来,同时max会自动减1,直到为0,强制断掉。 

对应的Tomcat的服务器端的配置:

keepAliveTimeout:表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且为超过过期时间,则该连接将一直保持。
maxKeepAliveRequests:表示该连接最大支持的请求数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)。

如果配置了上述的内容,可以解决BIO上面提出的第二个问题,当一个页面中的第一个请求后,后面的连接可以复用这个socket或者是socketchannel,不用再accept三次握手或者SSL握手了,相当于高效的推动了整体Tomcat的时间链条的处理效率,而对于keepAlive属性的加入,通过BIO和NIO对比测试发现,相当于放大了NIO的优势,导致NIO的测试结果要明显高于BIO一个水平线上,这也就是目前http1.1协议中,为什么Tomcat后续版本默认就是NIO的原因;而如果没有keepAlive属性加入,在大多数的场景下,NIO并没有拉开与BIO太大的差距,甚至有一些场景上,Tomcat的BIO模式反倒是比NIO要高;

这里单纯的对比性能没有任何的意义,因为性能测试是测试在不同应用类型,不同硬件环境,不同软甲版本,甚至是不同jdk性能差异都很大,客观因素很多,而且Tomcat的web服务器目前在企业应用或者是互联网应用上来看,都是其链条中的微小的时间占比环节,甚至有的长事务处理链条中,Tomcat这块占比不到1%,当然对于学习和研究,更高更快更强是技术追求的目的,这个就另当别论了。

后续会详细分析一下keepAlive的实现,还有APR,NIO2两个通道的实现,敬请期待。

c.BIO连接器与NIO连接器的对比的更多相关文章

  1. d.BIO连接器与NIO连接器的对比之二

    前面在Tomcat中讲解了两个通道,BIO和NIO,我们这里来通过两端程序,简单模拟两个通道,找找异同点: BIO: 1. public class SocketServer {    public ...

  2. Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

    目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. pack ...

  3. 连接器|网络滤波连接器|电脑连接器|RJ45变压器-华联威电子有限公司

    连接器|网络滤波连接器|电脑连接器|RJ45变压器-华联威电子有限公司  

  4. Revit MEP API找到连接器连接的连接器

    通过conn.AllRefs;可以找到与之连接的连接器. //连接器连接的连接器 [TransactionAttribute(Autodesk.Revit.Attributes.Transaction ...

  5. Java NIO 学习笔记(七)----NIO/IO 的对比和总结

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  6. EMS设置发送连接器和接收连接器邮件大小

    任务:通过EMS命令设置发送接收连接器和接收连接器的邮件大小限制值为50MB. 以Exchange管理员身份打开EMS控制台.在PowerShell命令提示符下. 键入以下命令设置接收-连接器的最大邮 ...

  7. 1、nio说明 和 对比bio

    nio和bio的区别 bio: 面向流的. 单向的. 阻塞的,这也是b这个的由来. nio: 面向块的.(buffer) 双向的. 非阻塞的.同步的编程方式.是一种select模型 nio编程的常规步 ...

  8. Java NIO学习系列四:NIO和IO对比

    前面的一些文章中我总结了一些Java IO和NIO相关的主要知识点,也是管中窥豹,IO类库已经功能很强大了,但是Java 为什么又要引入NIO,这是我一直不是很清楚的?前面也只是简单提及了一下:因为性 ...

  9. Java NIO学习笔记九 NIO与IO对比

    Java NIO与IO Java nio 和io 到底有什么区别,以及什么时候使用nio和io,本文做一个比较. Java NIO和IO之间的主要区别 下表总结了Java NIO和IO之间的主要区别, ...

随机推荐

  1. Android studio -VSN 使用笔记

    1.Android studio 安装 中文组官网:http://www.android-studio.org/ 常见问题参考: 分支冲突合并 http://blog.csdn.net/tearsmo ...

  2. php 关于stripslashes 和 addslashes的使用

    一.首先要先说到 php magic_quotes_gpc  .(get_magic_quotes_gpc()可以检测是否开启) PHP magic_quotes_gpc作用范围是:WEB客户服务端: ...

  3. 中兴F412光猫超级密码破解、破解用户限制、关闭远程控制、恢复路由器拨号

    不少家庭都改了光纤入户,那肯定少不了光猫的吧.今天以中兴F412光猫为例介绍下此型号光猫超级密码的破解方法.一.F412超级密码破解方法1.运行CMD,输入telnet 192.168.1.1: 2. ...

  4. jqzoom图片放大镜

    jqzoom是一个图片放大器插件.它功能强大,使用简便! 引入js与css: <script type="text/javascript" src="js/jque ...

  5. App软件开发的10个常用技巧

    移动应用市场用户争夺战日益激烈,原来做APP拼想法拼创意拼是否抓住用户痛点.现在,精细化用户体验成为了一个APP能否留存用户的关键问题,一旦用户觉得体验不畅,马上就有竞品APP后补,如何开发高性能的移 ...

  6. zabbix报警媒介------>微信报警

    zabbix报警媒介------>微信报警 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 欢迎加入高级运维工程师之路:598432640 微信在我们的生活中使用的比较频繁,有 ...

  7. ruby基础语法

    首发:个人博客,更新&纠错&回复 学不同语言,常将它们的基础语法搞混,例如if后面有没有(),后面是then还是:还是{,结尾是end还是}. 这种事情毫无技术含量又毫无乐趣可言,但极 ...

  8. tomcat部署https

    在server.xml配置文件中增加证书位置跟密码: <Connector port="443" protocol="org.apache.coyote.http1 ...

  9. convert \uXXXX String to Unicode Characters in Python3.x

    转换\uXXXX if Python3.x: str.decode no longer exists in 3.x. that']s why Python 3.4: str : AttributeEr ...

  10. Linux之一条命令解决常见问题(持续更新)

    # 1.删除0字节文件 find -type f -size 0 -exec rm -f {} \; # 2.批量文件重命名 find . -type f -name "*.txt" ...