NIO系列
【NIO系列】——之TCP探秘
网络的中的数据,最终通过多个路由器连接传送的。最底层的以太网协议规定了电子信号如何组成数据包,解决了局域网的点对点通信问题,但无法解决多个局域网的的互通问题。
而网络层采用的IP协议,就是定义了一套自己的地址规则,主要解决寻址和路由的功能,根据对方的IP地址,寻找最佳路径传输信息。局域网通过路由器连接,路由器基于IP协议,指导数据包向某个路由借口转发。但IP协议不保证包一定到达以及完整性,特别是
网络拥堵的时候,会丢弃一些数据包,保证数据的传送效率
。
而保证数据包的完整、有序以及可靠,这就是TCP 协议要来做的事情了。
很多网络有一个最大传送单元,它是链路层中的网络对数据帧的一个限制,以以太网为例,MTU为
1500个字节
。一个IP数据报在以太网中 传输,如果它的长度大于该MTU值,就要进行分片传输,使得每片数据报的长度小于MTU。 一个tcp包的在500字节
左右(默认MSS大小为563byte
),其大小小于MUT,以防止在网络层被分片处理。
其次增加SEQ和ACK,同时采用超时重发的机制来保证包的可靠性。
SYN (synchronous建立联机)
ACK (acknowledgement 确认)
PSH (push传送)
FIN (finish结束)
RST (reset重置)
URG (urgent紧急)
SEQ (Sequence number顺序号码)
ACK (Acknowledge number确认号码)
三次握手过程:
1.C->S: syn=1 seq=x ack=0
2.S->C: syn=1 seq=y ack=x+1
3.C->S: seq=x+1 ack=y+1
【NIO系列】——之IO模型
总结
针对这5中IO模型,我采用一张图来总结一下。
java IO
Unix中的五种I/O模型,除信号驱动I/O外,Java对其它四种I/O模型都有所支持。其中Java最早提供的blocking I/O即是同步阻塞I/O,而NIO即是同步非阻塞I/O,同时通过NIO实现的Reactor模式即是I/O复用模型的实现,通过AIO实现的Proactor模式即是异步I/O模型的实现。
所以说严格意义上来说,通过Reactor模式实现的NIO
,和unix中的I/O多路复用
是相同的概念,但这是一种编程模型
,而不是原生支持。这也是我们下面所要进行的netty讲解的主要思想。
【NIO系列】——之Reactor模型
其中Reactor线程,负责多路分离套接字,有新连接到来触发connect 事件之后,交由Acceptor进行处理,有IO读写事件之后交给hanlder 处理。
Acceptor主要任务就是构建handler ,在获取到和client相关的SocketChannel之后 ,绑定到相应的hanlder上,对应的SocketChannel有读写事件之后,基于racotor 分发,hanlder就可以处理了(所有的IO事件都绑定到selector上,有Reactor分发)。
该模型 适用于处理器链中业务处理组件能快速完成的场景。不过,这种单线程模型不能充分利用多核资源,所以实际使用的不多。
相对于第一种单线程的模式来说,在处理业务逻辑,也就是获取到IO的读写事件之后,交由线程池来处理,这样可以减小主reactor的性能开销,从而更专注的做事件分发工作了,从而提升整个应用的吞吐。
第三种模型比起第二种模型,是将Reactor分成两部分,
mainReactor负责监听server socket,用来处理新连接的建立,将建立的socketChannel指定注册给subReactor。
subReactor维护自己的selector, 基于mainReactor 注册的socketChannel多路分离IO读写事件,读写网络数据,对业务处理的功能,另其扔给worker线程池来完成。
我们可以看到,mainReactor 主要是用来处理网络IO 连接建立操作,通常一个线程就可以处理,而subReactor主要做和建立起来的socket做数据交互和事件业务处理操作,它的个数上一般是和CPU个数等同,每个subReactor一个线程来处理。
此种模型中,每个模块的工作更加专一,耦合度更低,性能和稳定性也大量的提升,支持的可并发客户端数量可达到上百万级别。关于此种模型的应用,目前有很多优秀的矿建已经在应用了,比如mina 和netty 等。上述中去掉线程池的第三种形式的变种,也 是Netty NIO的默认模式。
【NIO系列】——之Netty
采用官方的话来说:
Netty是一个高性能、异步事件驱动的网络应用框架。 基于Netty,可以快速的开发和部署高性能、 高可用的网络服务端和客户端应用。