Java进阶面霸 NIO开发需要知道的Netty精粹,JAVA

Netty是个高效的JAVANIO框架 , 总体框架基于异步非阻塞的设计 , 基于网络IO事件驱动 , 主要贡献在于可以让用户基于Netty提供的API快速开发高性能、高可靠性的网络应用 。 这篇文章主要是介绍Netty框架的基础技术——JAVANIO 。 这时候可能会有同学会有点小疑问 , 是异步IO(AIO)么?然而并不是 , 虽然JDK7也提供了异步IO(AIO)的接口 , 但是Netty曾经尝试过某个小版本 , 但是效果和NIO相比并没有什么优势 , 因此后面的版本Netty也把对AIO的支持废弃了 , 今天我们就来扒一下JAVANIO 。 四种IO模型简述
我们先从四种IO模型开始扒起 , 常见的IO模型有四种(这四种模型在网络上也有很多很多的资料 , 为较少篇幅本片将这部分内容压缩一下):
同步阻塞(BlockingIO):最简单的一种IO模型 , 用户线程在进行IO操作的时候通常是个系统调用 , 用户线程会由用户空间进入内核空间 , 内核空间数据包准备好后会将数据拷贝到用户空间 , 这个时候线程在用户态继续执行 。
同步非阻塞(Non-blockingIO):同步非阻塞IO即在同步阻塞的基础之上将socket设置为NONBLOCK 。 这样用户线程在发起IO操作之后可以立即返回 , 但是用户线程需要不断轮询来请求数据 。
IO多路复用(IOMultiplexing):即Reactor设计模式 , 多路复用模型从流程上和同步阻塞的区别不大 , 主要区别在于操作系统为用户提供了同时轮询多个IO句柄来查看是否有IO事件的接口(如select) , 这从根本上允许用户可以使用单个线程来管理多个IO句柄的问题 。
异步IO(AsynchronousIO):即Proactor设计模式 。 在异步IO模型中 , 用户不需要去轮询IO事件 , 然后才进行数据的读取 , 处理;在异步IO模型中 , IO事件就绪的时候 , 内核会开启一个独立的内核线程去执行执行IO操作 , 实现真正的异步IO 。 这个时候用户线程可以直接读取内核线程准备好的数据 。
多路复用IO模型和异步IO模型的区别主要是用户线程得知IO事件的时候在多路复用IO模型中 , 用户线程需要自己去处理IO , 而在异步IO模型中数据已经由内核线程为用户线程准备好了 。 在实际应用中 , 在高效的IO应用中 , 最常见的是第三种IO模型 , 异步IO目前操作系统方面的支持并不是很好而且在性能数据上并不是很好看 。
上面对四种IO模型进行了极其简单的概括 , 如多读者意犹未尽可以在网上查阅相关资料或者和作者联系 。 select、poll和epoll
JAVA对NIO的支持是从1.4版本开始的 , 是基于多路复用技术 , 而在linux操作系统方面多路复用技术有三种常用的机制:select、poll和epoll , epoll的支持也只是linux2.6版本之后才提供 , java在jdk5.0的update9之后才对epoll进行支持 。 这三种机制本质上都是同步IO , 主要是由于他们都需要在读写事件就绪的时候需要自己进行读写 , 也就是这个这个读写过程是阻塞的 。 下面对这三种机制进行简单总结:
select函数:该函数允许进程指示内核等待多个事件中的任何一个发生的时候或者在一定时间之后被唤醒 , select有个致命的缺点即在多路复用中文件描述符的数量有限制 , 如果需要突破限制需要重新编译操作系统内核 。
poll函数:poll机制与select机制类似 , 区别是poll没有最大描述符限制 。
epoll函数:epoll在linux2.6内核中被提出来 , 是之前的select和poll的增强版本 。 epoll也没有文件描述符数量限制 , 而且是用一个文件描述符来管理多个描述符 。 在性能上相比上面两种有了很大的优化 。
关于select、poll和epoll的详细介绍可以参考这里 。 JAVANIO
JAVA的NIO是基于IO多路复用模型 , 在不同平台上有不同的实现方式 。 Linux下面用的是poll和epoll , 在BSD上用kqueue , 在Windows上是重叠I/O 。
在JAVANIO中有三个核心的组件:Channels、Buffers和Selectors 。


推荐阅读