IO
linux内核将全部外部设备都看作一个文件来操做,对一个文件的读写会调用内核系统命令,放回一个file descriptor(文件描述符),
对一个socket的读写也会有相应的描述符,称为socketfd
Java NIO的核心类库多路复用器Selector就是基于epoll的多路复用技术实现
I/O多路复用技术经过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的状况下能够同时处理多个客户端请求
epoll和select的原理比较相似,并作了不少重大改进
1 支持一个进程打开的socket描述符(FD)不受限制(仅受限于操做系统的最大文件句柄数),1GB内存的机器上大约是10万个句柄左右,
具体值能够经过cat /proc/sys/fs/file- max查看
2 I/O效率不会随着FD数目的增长而线性降低,socket集合的维护成本上,epoll只会对活跃的socket进行操做,由于在内核实现中,
epoll是根据每一个fd上面的callback函数实现额,只有活跃的socket才会去主动调用callback函数
3 使用mmap加速内核与用户空间的消息传递,epoll是经过内核和用户空间mmap同一块内存来实现的
JDK1.7升级了原来的NIO类
1 提供可以批量获取文件属性的API,这些API具备平台无关性,另外还提供了标准文件系统的SPI,供各个服务提供商扩展的实现
2 提供AIO功能,支持基于文件的异步I/O操做和针对网络套接字的异步操做
3 完成了定义的通道功能,包括对配置和多播数据报的支持
同步阻塞I/O,阻塞的时间取决于对方I/O线程的处理速度和网络I/O的传输速度
伪异步I/O
采用线程池和任务队列能够实现一种叫作伪异步的I/O通讯框架
缺陷,当对Socket的输入流进行读取操做的时候,它会一直阻塞下去,直到发生以下三件事:1有数据可读2可用数据已经读取完毕3发生空指针或者I/O异常
伪异步I/O实际上仅仅是对以前I/O线程模型的一个简单优化,没法从根本上解决同步I/O致使的通讯阻塞问题
NIO(Non-block I/O)
与Socket类和ServerSocket类相对应,NIO也提供了SocketChannel和ServerSocketChannel两种不一样的套接字通道实现,这两种新增的通道同时支持阻塞和非阻塞两种模式
NIO弥补了原来同步阻塞I/O的不足,在标准Java代码中提供了高速的、面向块的I/O
在NIO类库中加入了Buffer(缓冲区)对象,体现了新库与原I/O的一个重要区别,缓冲区不只仅是一个数组,还提供了对数据的结构化访问以及维护读写位置等信息
每一种Java基本类型(除了Boolean类型)都对应有一种缓冲区,大多数标准I/O操做都使用ByteBuffer
Channel是一个通道,通道与流的不一样之处在于通道时双向的,流只是在一个方向上移动,而通道能够用于读、写或者两者同时进行,Channel是全双工的,
UNIX底层操做系统通道都是全双工的,因此它能够更好的映射底层操做系统API
Channel分为两大类:用于网络读写的SelectableChannel和用于文件操做的FileChannel
多路复用器Selector
多路复用器提供选择已经就绪的任务的能力,Selector会不断地轮询注册在其上的Channel,若是某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,
而后经过SelectionKey能够获取就绪Channel的集合,进行后续的I/O操做,因为JDK使用了epoll代替了传统的select实现,因此它并无最大链接句柄1024/2048的限制
AIO
NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现,异步通道提供如下两种方式获取操做结果
1 经过java.util.concurrent.Future类来表示异步操做的结果
2 在执行异步操做的时候传入一个java.nio.channels
它不须要经过多路复用器对注册的通道进行轮询操做便可以实现异步读写
Netty
TCP粘包拆包
使用LineBasedFrameDecoder和StringDecoder能够解决TCP粘包致使的读半包问题,这二者的组合就是按行切换的文本解码器
DelimiterBasedFrameDecoder自动完成以分隔符作结束标志的消息的解码
FixedLengthFrameDecoder能够自动完成对定长消息的解码
编解码技术
基于JDK默认的序列化机制可让程序员避免操做底层的字节数组,序列化的目的主要是网络传输和对象持久化
当进行跨进程服务调用时,须要把被传输的Java对象编码为字节数组或者ByteBuffer对象,而当远程服务读取到ByteBuffer对象或字节数组时,须要将其 解码为发送时的Java对象,这被称为Java对象编解码技术,Java序列化仅仅是Java编解码技术的一种
采用JDK序列化机制编码后的二进制数组大小是二进制编码的5倍多
编解码框架的优点每每从如下几个方面考量:是否支持跨语言,编码后的码流大小,编解码的性能,类库是否小巧方便使用
协议栈开发就是基于现有的基础协议(eg http协议)进行的封装扩展
WebSocket协议开发
HTTP协议的弊端 半双工协议,在客户端和服务端两个方向上传输,可是不能同时传输;消息采用文本传输,冗长繁琐;长时间轮询
比较新的一种轮询技术是Comet,使用AJAX,这种技术虽然能够达到双向通讯,但依然须要发出请求,并且广泛使用了长链接,会大笑消耗带宽和资源
HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯