io模型搞得我非常头大,理解不了,不清楚,整理一篇博客。
学习io模型首先要弄明白同步和异步,阻塞和非阻塞。
最开始学习io的时候,我以为同步就是阻塞,异步就是非阻塞,然而并不是这样。
什么同步io,异步io,阻塞io,非阻塞io都不清楚。
目录
同步、异步 & 阻塞、非阻塞
1,同步:
发起一个调⽤用,没得到结果前,不返回;一旦返回,就肯定得到了结果。
如果有多个任务或者事件要发生,这些任务或者事件必须逐个地进行,一个事件或者任务的执行会导致整个流程的暂时等待,这些事件没有办法并发地执行;
2,异步:
发起⼀个调⽤用,直接返回,没结果;之后,通过通知、回调⽅方式获取结果。
如果有多个任务或者事件发生,这些事件可以并发地执行,一个事件或者任务的执行不会导致整个流程的暂时等待。
3,阻塞:
调⽤结果返回前,当前线程会被挂起;直到拿到结果才被唤醒
4,非阻塞:
不能立刻得到结果之前,该调⽤不会阻塞当前线程
阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
第2条有点问题,应该是,老张把水壶放火上(得到一个最初的通知水没开),时不时去看水有没有开,直到水开。
第3、4条,响水壶水开了,会响,相当于放一个通知。
异步就好比调用后就直接去做其他事情,不用同步等待,在等一个通知
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模型也需要了解下
说点什么
1 评论 在 "io模型"
[…] io模型 […]