目录
IO模型:BIO NIO AIO io多路复用模型
BIO,NIO,AIO(Java中的NIO就是多路复用,linux中的NIO是指普通的非阻塞IO)
(AIO异步 AIO是每个请求从一开始就分配一个线程,实现了真正的异步处理。但是这也会带来一个问题,线程池中线程的数量不是无限的,如果每个请求从一开始就分配线程进行处理,很快就会用完线程。故netty用的不是Aio而是Nio ,netty的异步指的是 多线程处理结果)
BIO
阻塞:在accept和read方法会发生阻塞,(阻塞的意思是当前线程 没有连接建立或者没有读到数据,就不会往下执行,阻塞等待,不会占用cpu,但线程相当于闲置。非阻塞即使没有连接,没有读到数据,也会往下执行,只不过accept等于null读到的值为0.)单线程版的阻塞,如果没有新的accept就不会read,只有有了新连接才会往下执行read,这样单线程显得力不从心,太笨重了,可以引入多线程技术,如果连接数过多,会oom,并且线程过大,反而因为线程上下文切换,导致性能降低。即使引进线程池版,如果多个连接建立了 但是inactive,也会阻塞线程。不适合长连接。适合短链接。
如果BIO使用单线程接受连接,则会阻塞其他连接,效率较低。
如果使用多线程虽然减弱了单线程带来的影响,但当有大并发进来时,会导致服务器线程太多,压力太大而崩溃。
就算使用线程池,也只能同时允许有限个数的线程进行连接,如果并发量远大于线程池设置的数量,还是与单线程无异。
NIO
非阻塞:即使没有连接,没有读到数据,也会往下执行,只不过accept等于null读到的值为0.缺点:cpu利用率过高,会发生空轮转,即没有新连接也会向下执行,cpu会100%。白白浪费cpu,线程复制过程中,线程实际上还是阻塞的(aio改进的地方)
由此引进Nio 基于io多路复用的单线程事件监听机制,非阻塞模式下
基于事件驱动(基于io多路复用)的非阻塞,即只会有连接建立的时候才去访问,只要有数据可读的时候才去读。
selector.select()也是阻塞的,没有事件就会阻塞,有事件才会向下执行运行。(无事件阻塞,有事件非阻塞)。selector什么实话2不阻塞:1,channel可写的时候,2,客户端发起连接的时候,会触发accept(),客户端发送数据时,客户端关闭时(正常或异常)会触发read事件,另外如果发送的数据大于buffer缓冲区的大小 ,会多次触发read事件。3,再linux下,nio bug发生的时候。(即使没有数据,也会向下执行)selector.wakeup() selector.close() selector所在线程interrupt。
以上nio是基于单线程,但是现在cpu都是多核的,没有充分利用cpu。所以你也可以用多线程。
nio三大组件:channel selector buffer
- channel(和 stream都是全双工,读写可以同时进行)
- selector:创建selector :Selector selector=Selector.open();建立selector和channel之间的关系并得到selectionKeys SelectionKeys ssckeys= ssc.register(selector,0,null); ssckey关心的是accept事件 :ssckey.interestOps(SelectKeys.OP_ACCEPT) 然后select()方法 监听事件的发生。
- buffer
引出netty
Netty是异步 基于事件驱动的网络应用框架(此处的异步是指 多线程去回调read,write,accept结果,不会阻塞住。io模型还是基于多路复用的,通过selector监听是否有可读可写 可连接状态,如果没有阻塞住 不向下执行,如果有的话 就去执行监听到的事件。)