Welcome everyone

io模型

java 汪明鑫 884浏览 1评论

io模型搞得我非常头大,理解不了,不清楚,整理一篇博客。

 

学习io模型首先要弄明白同步和异步,阻塞和非阻塞。

最开始学习io的时候,我以为同步就是阻塞,异步就是非阻塞,然而并不是这样。
什么同步io,异步io,阻塞io,非阻塞io都不清楚。

 

同步、异步 & 阻塞、非阻塞

1,同步:

发起一个调⽤用,没得到结果前,不返回;一旦返回,就肯定得到了结果。

如果有多个任务或者事件要发生,这些任务或者事件必须逐个地进行,一个事件或者任务的执行会导致整个流程的暂时等待,这些事件没有办法并发地执行;

相对于IO操作而言的,在同一时间,只能去完成一个操作

2,异步:

发起⼀个调⽤用,直接返回,没结果;之后,通过通知、回调⽅方式获取结果。

如果有多个任务或者事件发生,这些事件可以并发地执行,一个事件或者任务的执行不会导致整个流程的暂时等待。

在同一时间同时完成多个操作
可以把开启一个线程当作异步操作,
还有一些异步中间价,比如kafka

3,阻塞:

调⽤结果返回前,当前线程会被挂起;直到拿到结果才被唤醒

相对数据而言,判断数据有没有准备好,没有准备好,程序就塞住
等待数据到来

4,非阻塞:

不能立刻得到结果之前,该调⽤不会阻塞当前线程

不管数据有没有准备好,都会给一个反馈
同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

 

第2条有点问题,应该是,老张把水壶放火上(得到一个最初的通知水没开),时不时去看水有没有开,直到水开。

第3、4条,响水壶水开了,会响,相当于放一个通知。

 

异步就好比调用后就直接去做其他事情,不用同步等待,在等一个通知

 

io模型

 

 

 

 

 

其中while循环前将socket添加到select监视中,然后在while内一直调用select获取被激活的socket,一旦socket可读,便调用read函数将socket中的数据读取出来。
然而,使用select函数的优点并不仅限于此。虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只注册自己感兴趣的socket或者IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率。

 

通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。

 

异步IO模型中,用户线程直接使用内核提供的异步IO API发起read请求,且发起后立即返回,继续执行用户线程代码。不过此时用户线程已经将调用的AsynchronousOperation和CompletionHandler注册到内核,然后操作系统开启独立的内核线程去处理IO操作。当read请求的数据到达时,由内核负责读取socket中的数据,并写入用户指定的缓冲区中。最后内核将read的数据和用户线程注册的CompletionHandler分发给内部Proactor,Proactor将IO完成的信息通知给用户线程(一般通过调用用户线程注册的完成事件处理函数),完成异步IO。

 

一般IO多路复用模型是同步非阻塞的

 

举个例子帮我们更好的理解:

1.阻塞I/O模型
老李去火车站买票,排队三天买到一张退票。
耗费:在车站吃喝拉撒睡 3天,其他事一件没干。

2.非阻塞I/O模型
老李去火车站买票,隔12小时去火车站问有没有退票,三天后买到一张票。耗费:往返车站6次,路上6小时,其他时间做了好多事。

3.I/O复用模型
1.select/poll
老李去火车站买票,委托黄牛,然后每隔6小时电话黄牛询问,黄牛三天内买到票,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,黄牛手续费100元,打电话17次
2.epoll
老李去火车站买票,委托黄牛,黄牛买到后即通知老李去领,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,黄牛手续费100元,无需打电话

4.信号驱动I/O模型
老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,免黄牛费100元,无需打电话

5.异步I/O模型
老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门。
耗费:往返车站1次,路上1小时,免黄牛费100元,无需打电话

两种高性能IO设计模式

在传统的网络服务设计模式中,有两种比较经典的模式:

一种是 多线程,一种是线程池。

对于多线程模式,也就说来了client,服务器就会新建一个线程来处理该client的读写事件

这种模式虽然处理起来简单方便,但是由于服务器为每个client的连接都采用一个线程去处理,使得资源占用非常大。因此,当连接数量达到上限时,再有用户请求连接,直接会导致资源瓶颈,严重的可能会直接导致服务器崩溃。

  因此,为了解决这种一个线程对应一个客户端模式带来的问题,提出了采用线程池的方式,也就说创建一个固定大小的线程池,来一个客户端,就从线程池取一个空闲线程来处理,当客户端处理完读写操作之后,就交出对线程的占用。因此这样就避免为每一个客户端都要创建线程带来的资源浪费,使得线程可以重用。

  但是线程池也有它的弊端,如果连接大多是长连接,因此可能会导致在一段时间内,线程池中的线程都被占用,那么当再有用户请求连接时,由于没有可用的空闲线程来处理,就会导致客户端连接失败,从而影响用户体验。因此,线程池比较适合大量的短连接应用。

于是出现了2种高性能IO设计模式

Reactor和Proactor,再上面的介绍中也已经出现过了。

在Reactor模式中,会先对每个client注册感兴趣的事件,然后有一个线程专门去轮询每个client是否有事件发生,当有事件发生时,便顺序处理每个事件,当所有事件处理完之后,便再转去继续轮询。

多路复用IO就是采用Reactor模式。图中展示的是顺序处理每个事件,为了提高事件处理速度,可以通过多线程或者线程池的方式来处理事件。

在Proactor模式中,当检测到有事件发生时,会新起一个异步操作,然后交由内核线程去处理,当内核线程完成IO操作之后,发送一个通知告知操作已完成,异步IO模型采用的就是Proactor模式。

直接IO & 缓存IO

缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中,以write为例,数据会先被拷贝进程缓冲区,在拷贝到操作系统内核的缓冲区中,然后才会写到存储设备中。

 

 

零拷贝

零拷贝(zero-copy)技术可以减少数据拷贝和共享总线操作的次数,消除通信数据在存储器之间不必要的中间拷贝过程,有效地提高通信效率,是设计高速接口通道、实现高速服务器和路由器的关键技术之一。数据拷贝受制于传统的操作系统或通信协议,限制了通信性能。采用零拷贝技术,通过减少数据拷贝次数,简化协议处理的层次,在应用和网络间提供更快的数据通路,可以有效地降低通信延迟,增加网络吞吐率。

简单来说,零拷贝可以避免无谓的copy动作。

 

HTTP/2的多路复用

HTTP/2的多路复用就是为了解决上述的两个性能问题

 

解决第一个的问题

在HTTP1.1的协议中,我们传输的request和response都是基本于文本的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello world,只能从h到d一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序,所以并行传输在HTTP1.1是不能实现的。

HTTP/2引入二进制数据帧的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的传输数据,这就是所做的事情。

 

解决第二个的问题

HTTP/2对同一域名下所有请求都是基于,也就是说同一域名不管访问多少文件,也只建立一路连接。同样Apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了6倍!

 

 

 

小结

io相关问题水很深,涉及的很多,之后再以这篇整理的博客为基础慢慢的学习。

容易混淆的概念(面试经常会问到):同步和异步,阻塞和非阻塞
io模型要了解下
面试会经常问到BIO和NIO的区别
阻塞体现在哪里?

 

之后需要学习的io相关知识:

io包和nio包的重要api要敲一遍,关键源码要看下

要深入理解io模型,就要看相关的书籍

netty的学习

tomcat,mysql,redis,netty用了哪些io模型也需要了解下

 

转载请注明:汪明鑫的个人博客 » io模型

喜欢 (0)

说点什么

1 评论 在 "io模型"

提醒
avatar
排序:   最新 | 最旧 | 得票最多
trackback

[…] io模型 […]

wpDiscuz