说说高并发IO原理及模型,结果没结果了

存储 存储软件
read调用,并不是直接从物理磁盘读取,同样,write调用也不是直接把数据写进物理磁盘,在他们中间还有一层,就是缓冲区,而缓冲区又包括:内核(kernel)缓冲区和用户进程缓冲区。

 被虐前奏

面试官:说一下高并发IO底层原理?

面试者:呃。。。嗯。。。这个那个。。。我们都是用XX框架

结果:卒

理解一下高并发原理,展现真正的实力

[[324201]]

一、IO读写基础原理

IO读写分为read和write两块,在不同的操作系统中,IO读写的底层调用可能有些区别,但基本功能是一样的。read调用,并不是直接从物理磁盘读取,同样,write调用也不是直接把数据写进物理磁盘,在他们中间还有一层,就是缓冲区,而缓冲区又包括:内核(kernel)缓冲区和用户进程缓冲区。具体可以看下图

 

面试官:说说高并发IO原理及模型,结果没结果了

 

在Java中,完整的Socket请求和响应如下:

  • 客户端调用:系统通过网卡读取客户端的请求,将数据读取到内核缓冲区;
  • 程序请求数据:Java通过read命令,将数据从内核缓冲区送入Java的用户缓冲区;
  • Java服务端数据处理:在Java用户空间中处理客户请求数据;
  • Java服务端返回数据:数据处理完,通过write命令,将构建好的响应数据从用户缓冲区写入内核缓冲区;
  • 发送数据到客户端:内核通过网络IO,将内核缓冲区中的数据通过网卡,适时将数据发送给目标客户端。

二、四种常见的IO模型

1、同步阻塞IO(Blocking IO)

我们先了解一下概念:

同步与异步:同步指的是用户空间是主动发起IO请求的一方,内核空间是被动接受的一方;异步则是将以上过程反过来;

阻塞与非阻塞:阻塞指的用户空间发起请求后,需要等待内核空间彻底完成后,才将数据返回到用户空间;非阻塞指的是用户空间不需要等待内核空间操作完成,可以立即返回用户用户空间的过程 。

传统的IO模型都是同步阻塞IO,在Java中,默认创建的socket都是同步阻塞的。Java应用从发起IO调用开始,直到系统调用返回,Java进程都是阻塞的,直到有数据返回成功后,应用程序才能开始处理用户缓冲区的数据,具体流程如下:

 

面试官:说说高并发IO原理及模型,结果没结果了

 

由上图可以看出,每一步必须等待上一步的完成才能进行。

同步阻塞IO优点:开发简单,容易入门;在阻塞等待期间,用户线程挂起,在挂起期间不会占用CPU资源。

同步阻塞IO缺点:一个线程维护一个IO,不适合大并发,在并发量大的时候需要创建大量的线程来维护网络连接,内存、线程开销灰常大。

2、同步非阻塞IO(Non-blocking IO)

参考以上概念,当处于非阻塞IO时,用户空间与内核空间可以更快的交互,只要拿到内核返回的状态值,就可以继续干自己的事情,而不用做无谓的等待。

在Java中,将socket的属性设置为NONBLOCK即为非阻塞模式。在这个模式中,会有以下两种情况:

在内核缓冲区没有数据时,系统调用会马上返回失败状态给调用方;

在内核缓冲区有数据时,此时是会阻塞的,直到数据从内核缓冲区复制到用户缓冲区,复制完成后,系统调用返回成功,继而用户的应用进程开始处理用户空间的数据,具体流程如下:

 

面试官:说说高并发IO原理及模型,结果没结果了

 

由上图可以看出,在内核还没有准备好数据的时候,用户线程发起IO请求,会立即返回;为了最终读取到数据,用户线程需要不断发起IO调用;历经多次探险后,终于有数据到达内核时,此时,用户线程会进入阻塞状态,当数据成功复制到用户缓冲区,用户线程成功读取到数据后,才会解除阻塞状态,重新运行起来。

同步非阻塞IO优点:每次发起IO调用,在内核等待数据的过程中可以立即返回,用户线程不会阻塞,实时性较好。

同步非阻塞IO缺点:多个线程不断轮询内核是否有数据,占用大量CPU时间,效率不高。一般Web服务器不会采用此模式。

3、IO多路复用(IO Multiplexing)

如何解决同步非阻塞IO轮询造成效率低下的问题,这时IO多路复用出现了。

经典的Reactor反应器设计模式,也可称为异步阻塞IO,是众多高性能高并发服务器的基础,比如Nginx、Netty、Redis等。Java中NIO(New IO)里的Selector选择器也是基于此模式。在Linux系统中,对应的系统调用为select/epoll系统调用,当内核缓冲区可读或者可写时,内核将就绪的状态主动通知相应的用户程序,应用程序收到就绪状态,进行相应的IO调用,具体流程如下:

 

面试官:说说高并发IO原理及模型,结果没结果了

 

由上图可以看出,该模式下,read操作流程如下:

  • 注册选择器,将read操作的目标socket提前注册到select/epol选择器中(类比Java中NIO的selector);
  • 轮询,通过选择器的查询方法,查询注册过的所有socket连接的就绪状态,内核个就绪的socket列表(当内核监控到注册过的socket有数据准备好了,就会将该socket加入到就绪列表)。注意,当用户调用select查询方法时,此时整个线程会处于阻塞状态;
  • 用户线程获取到就绪列表后,根据其中的socket连接,发起read请求,用户线程阻塞,内核开始复制数据,将数据从内核缓冲区复制到用户缓冲区;
  • 复制完成后,内核返回结果,用户线程才会解除阻塞,待用户线程读取成功数据后,线程继续。

IO多路复用优点:系统不必创建维护大量线程,只使用一个线程,一个选择器即可同时处理成千上万个连接,大大减少了系统开销。

IO多路复用缺点:本质上,select/epoll系统调用是阻塞式的,属于同步IO,需要在读写事件就绪后,由系统调用进行阻塞的读写。

4、异步IO(Asynchronous IO)

异步IO,指的是用户空间与内核空间的调用方式返过来。内核空间是主动调用者,用户空间变成被动接收者。用户空间的线程向内核空间注册各种IO事件的回调函数,由内核主动触发调用。

AIO的基本流程是:用户线程通过系统调用,向内核注册某个IO操作。在整个内核的数据处理中, 包括数据从网卡到内核缓冲区,内核缓冲区到用户缓冲区,用户程序都不需要阻塞。具体流程如下:

 

面试官:说说高并发IO原理及模型,结果没结果了

 

由上图可以看出,该模式下,在内核等待数据和复制数据的两个阶段,用户线程都不会阻塞。read操作流程如下:

  • 用户发起read请求,内核立刻返回成功状态,用户不会阻塞,可以马上去做其它事情;
  • 内核开始准备数据,待数据准备好了,内核会主动将数据从内核缓冲区复制到用户缓冲区;
  • 此时,内核会给用户线程发送一个信号,或者回调用户线程注册的回调接口,通知用户read操作完成了;
  • 用户线程收到通知后,读取用户缓冲区的数据,完成后续业务。

异步IO优点:真正实现了异步非阻塞,吞吐量在这几种模式中是最高的。

异步IO缺点:应用程序只需要进行事件的注册与接收,其余工作都交给了操作系统内核,所以需要内核提供支持。在Linux系统中,异步IO在其2.6才引入,目前也还不是灰常完善,其底层实现仍使用epoll,与IO多路复用相同,因此在性能上没有明显占优。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2024-01-10 08:01:55

高并发场景悲观锁

2021-07-01 07:34:09

LinuxIO模型

2020-04-10 08:03:04

分布式锁Redlock算法流行算法

2020-05-19 13:18:45

网页前端Web

2018-12-18 14:08:01

Java内存volatile

2018-03-01 15:13:42

Ryzen APU内存通道

2010-01-14 10:52:13

VB.NET水晶报表

2009-10-13 14:50:19

C#中b=a

2022-08-01 10:15:06

AI模型Meta

2009-09-14 10:09:26

LINQ查询结果

2020-09-02 07:05:56

手机支付

2020-09-22 12:00:23

Javahashmap高并发

2019-05-27 08:11:13

高并发Synchronize底层

2011-08-30 10:22:14

MongoDB

2019-06-28 10:55:04

预热高并发并发高

2020-09-23 22:36:27

分布式架构系统

2009-09-09 11:14:04

Linq多个结果集

2009-09-09 10:58:58

Linq结果集形状

2010-01-04 15:34:18

2020-04-13 08:33:39

高并发秒杀系统
点赞
收藏

51CTO技术栈公众号