java IO网络编程
1 java IO简介
1 Linux网络IO模型
Linux的内核将所有外部设备都看做一个文件来操作,对一个文件的读写操作会调用内核提供的系统命令,返回一个fd(文件描述符),而对于一个socket读写也会有描述符 socketfd。
描述符就是一个数字,指向内核中的一个结构体(文件路径,数据区等属性)
unix提供了5中IO模型:
-
1 阻塞IO模型
-
2 非阻塞IO模型
-
3 IO复用模型
Linux提供select/poll,顺序扫描fd是否就绪 和 epoll系统调用实现,epoll使用基于事件驱动方式代替顺序扫描,因此性能更好 -
4 信号驱动IO模型
-
5 异步IO
异步IO与信号驱动的区别是,信号由内核通知进程,何时可以开始一个IO操作,而异步IO是内核通知进程,IO操作已经完成
注意: 操作系统底层支持异步IO通信
2 IO多路复用技术
java NIO的核心类库多路复用器是基于epollo的多路复用技术实现的,即IO复用模型
IO多路复用就是把多个IO阻塞复用到同一个select的阻塞上,从而使系统在单线程的情况下爱可以同时处理多个客户端请求
epollo相比select有很多改进:
- 1 支持一个进程打开的socketfd不受限制,上限是操作系统的最大文件句柄数,1GB内存机器约10万个,而select默认只有1024。
- 2 IO效率不会随着FD数目增加而线性下降,select每次会扫描全部,所以效率会下降,而epoll只会对活跃的socket进行操作
- 3 使用mmap加速内核与用户空间的消息传递,mmap是内核和用户空间使用的同一个内存块
- 4 epoll的api更加简单
3 java IO 的演进
- 1 从jdk1.0 到 1.3,java的IO类库都很原始
- 2 2002年发布的jdk1.4开始支持非阻塞IO,提供了新的NIO类库,比如ByteBuffer,SocketChannel等,但是依然有不足,比如AP能力弱,比如递归需要自己实现,所有文件操作都是同步阻塞调用等
- 3 2011年 jdk1.7发布, NIO升级为 NIO2.0,提供AIO功能,批量获取文件属性API等
IO编程
1 传统BIO
当客户端并发访问后,服务器线程会非常多,性能急剧下降
2伪异步IO
这种模式其实就是引入了线程池,但是实际底层还是同步的只不过线程池设置了最大线程,避免服务器一直创建线程而导致服务崩溃
这种模型有很多缺点,比如所有可用线程都阻塞时候,后续请求会一直无限等待
3 NIO
NIO提供了和阻塞IO不同的套接字,SocketChannel和ServerSocketChannel,下面简单说一下NIO的类库:
- 1 Buffer,NIO中,任何读取和写入都是从Buffer中进行的,Buffer其实是一个字节数组最常用的Buffer是ByteBuffer
- 2 Channel, 通道,用来读取和写入数据,通道是双向的,既可以读也可以写,而流是单向的
- 3 多路复用器 Selector,他是java NIO 编程的基础,提供选择已经就绪任务的能力,多路复用器会不断轮询注册再其上的Channel,如果某个CHannel上有新的TCP连接接入,读和写事件,这个Channel就处于就绪状态,然后通过SelectionKey获取就绪CHannel的集合,进行后续的IO操作,一个Selector剋接入成千上万的客户端
4 AIO
jdk7升级了NIO类库,是真正的异步非阻塞IO,它对应UNIX网络编程中的事件驱动IO,不需要通过多路复用器对注册的通道进行轮询,即可实现异步读写,从而简化了NIO的编程模型
5 四种IO对比总结
选择netty