声明:本文是《Netty 权威指南》的样章,感谢博文视点授权并发编程网站发布样章,禁止以任何形式转载此文。
2.5.1.概念澄清
为了防止由于对一些技术概念和术语的理解或者叫法不一致引起歧义,本小节特意对本书中的专业术语或者技术用语做下声明,如果它们与其它的一些技术书籍术语不一致,请以本小节的解释为准。
2.5.1.1. 异步非阻塞IO
很多人喜欢将JDK1.4提供的NIO框架称为异步非阻塞IO,但是,如果严格按照Unix网络编程模型和JDK的实现进行区分,实际上它只能被称为非阻塞IO,不能叫异步非阻塞IO。在早期的JDK1.4和1.5 update10版本之前,JDK的Selector基于select/poll模型实现,它是基于IO复用技术的非阻塞IO,不是异步IO。在JDK1.5 update10和linux core2.6以上版本,sun优化了Selctor的实现,它底层使用epoll替换了select/poll,上层的API并没有变化,我们可以认为是JDK NIO的一次性能优化,但是它仍旧没有改变IO的模型。相关优化的官方说明如下:
JDK1.7提供的NIO2.0,新增了异步的套接字通道,它是真正的异步IO,在异步IO操作的时候可以传递信号变量,当操作完成之后会回调相关的方法,异步IO也被称为AIO。
NIO类库支持非阻塞读和写操作,相比于之前的同步阻塞读和写,它是异步的,因此很多人习惯于称NIO为异步非阻塞IO,包括很多介绍NIO编程的书籍也沿用了这个说法。为了符合大家的习惯,本书也会将NIO称为异步非阻塞IO或者非阻塞IO,请大家理解,不要过分纠结在一些技术术语的咬文嚼字上。
2.5.1.2. 多路复用器Selector
几乎所有的中文技术书籍都将Selector翻译为选择器,但是实际上我认为这样的翻译并不恰当,选择器仅仅是字面上的意思,这样翻译体现不出Selector的功能和特点。
在前面的章节我们介绍过Java NIO的实现关键是通过多路复用IO技术实现的,多路复用的核心就是通过Selector来轮询注册在其上的Channel,当发现某个或者多个Channel处于就绪状态后,从阻塞状态返回就绪的Channel的选择键集合,进行IO操作。由于多路复用器是NIO实现非阻塞IO的关键,它又是主要通过Selector实现,所以本书将Selector翻译为多路复用器,它与其它技术书籍所说的选择器是同一个东西,请大家了解。
2.5.1.3. 伪异步IO
伪异步IO的概念完全来源于实践,在JDK NIO编程没有流行之前,为了解决Tomcat通信线程同步IO导致业务线程被挂住的问题,大家想到了一个办法,就是在通信线程和业务线程之间做个缓冲区,这个缓冲区用于隔离IO线程和业务线程间的直接访问,这样业务线程就不会被IO线程阻塞,对于后端的业务侧来说,将消息或者Task放到线程池后就返回了,它不再直接访问IO线程或者进行IO读写,这样也就不会被同步阻塞。类似这样的设计还包括前端启动一组线程,将接收的客户端封装成Task,放到后端的线程池执行,用于解决一连接一线程问题,类似这样通过线程池做缓冲区的做法,我们习惯称它为伪异步IO,官方并没有伪异步IO这种说法。
下面的小节我们对几种常见的IO进行对比,以便大家能够理解几种IO的差异。
2.5.2.不同IO模型对比
不同的IO模型由于线程模型、API等差别很大,所以它们的用法差异也非常大。由于之前的几个小节已经集中对这几种IO的API和用法进行了说明,本小节重点对这几种IO进行功能对比。
尽管本书是专门介绍NIO框架Netty的,但是,并不意味着所有的Java网络编程都必须要选择NIO和Netty,具体选择什么样的IO模型或者NIO框架,完全基于业务的实际应用场景和性能诉求,如果客户端并发连接数不多,周边对接的网元不多,服务器的负载也不重,那就完全没必要选择NIO做服务端;如果是相反情况,那就要考虑选择合适的NIO框架进行开发。
对比完Java的几种主流IO模型之后,我们继续看下为什么要选择Netty进行NIO开发,而不是直接使用JDK的NIO原生类库。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/140612.html