网络IO模型
- 多路复用:是通信领域的术语,指把多个信号组合起来在一条物理信道上进行传输,在远距离传输时可大大节省电缆的安装和维护费用。这里指让一个线程或进程同时处理多个网络连接
- 事件多路分离(Event Demultiplexer):分离器对象可将来自事件源的I/O事件分离出来,并分发到对应的read/write事件处理器(Event Handler)。开发人员预先注册需要处理的事件及其事件处理器(或回调函数);事件分离器负责将请求事件传递给事件处理器(an object that dispatches I/O events from a limited number of sources to the appropriate read/write event handlers. The developer registers interest in specific events and provides event handlers, or callbacks. The event demultiplexor delivers the requested events to the event handlers.)
- 可以将输入操作io分为两个步骤:
* 内核等待数据准备好; * 将数据从内核缓冲区复制到进程缓冲区
Linux系统支持的典型I/O模型包含下面5种:
- 阻塞I/O(blocking I/O)
- 非阻塞I/O(nonblocking I/O)
- I/O多路复用(I/O multiplexing, e.g. select and poll)
- 信号驱动型I/O(signal driven I/O, e.g. SIGIO)
- 异步I/O(asynchronous I/O, e.g. the POSIX aio_* functions)
同步(synchronous):A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
异步(asynchronous):An asynchronous I/O operation does not cause the requesting process to be blocked.
按照这种定义,上面介绍的前4中IO模型均是同步的,因为真正的IO操作函数在进行数据读/写时,均会阻塞进程;只有异步IO模型真正符合异步IO操作的定义。
同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO。
阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。
- 传统的Java BIO (blocking I/O)是Unix I/O模型中的第一种。
- Java NIO中如果不使用select模式,而只把channel配置成nonblocking则是第二种模型。
- Java NIO select实现的是一种多路复用I/O。 底层使用epoll或者相应的poll系统调用
- 第四种模型JDK应该是没有实现。
- Java NIO2增加了对第五种模型的支持,也就是AIO。
Java 和Netty epoll实现
Oracle JDK在Linux已经默认使用epoll方式, 为什么netty还要提供一个基于epoll的实现呢?
Netty的核心开发者 Norman Maurer这么说的:
- Netty的 epoll transport使用 epoll edge-triggered(边缘触发) 而 java的 nio 使用 level-triggered(水平触发)
- 另外netty epoll transport 暴露了更多的nio没有的配置参数, 如 TCP_CORK, SO_REUSEADDR等等