前言

在使用Netty改造手写RPC框架的时候,需要给大家介绍一些相关的知识,这样很多东西大家就可以看明白了,手写RPC是一个支线任务,后续重点仍然是Kubernetes相关内容。

阻塞与非阻塞 同步与异步

阻塞与非阻塞

阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪的一种处理方式。当数据没有准备的时候,阻塞需要等待调用结果返回之前,进程会被挂起,函数只有在得到结果之后才会返回。非阻塞和阻塞的概念相对,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

同步与异步

同步指的是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。异步的概念和同步相对,当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

举个例子来说,对于我们经常使用B/S架构来说,同步和异步指的是从客户端发起访问数据的请求,阻塞和非阻塞指的是服务端进程访问数据,进程是否需要等待。这两者存在本质的区别,它们的修饰对象是不同的。

阻塞和非阻塞是指进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪。

同步和异步是指访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞,异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。

举个例子

妈妈让我去厨房烧一锅水,准备下饺子。

阻塞:水只要没烧开,我就干瞪眼看着这个锅,沧海桑田,日新月异,我自岿然不动,厨房就是我的家,烧水是我的宿命;

非阻塞:我先去我屋子里打把王者,但是每过一分钟,我都要去厨房瞅一眼,生怕时间长了,水烧干了就坏了,这样导致我游戏也心思打,果不然,又掉段了;

同步:不管是每分钟过来看一眼锅,还是寸步不离的一直看着锅,只要我不去看,我就不知道水烧好没有,浪费时间啊,一寸光阴一寸金;

异步:我在淘宝买了一个电水壶,只要水开了,它就发出响声,嗨呀,可以安心打王者喽,打完可以吃饺子喽;

总结:

阻塞/非阻塞:我在等你干活的时候我在干啥?

阻塞:啥也不干,死等;

非阻塞:可以干别的,但也要时不时问问你的进度;

同步/异步:你干完了,怎么让我知道呢?

同步:我只要不问,你就不告诉我;

异步:你干完了,直接喊我过来就行;

IO模型

网络IO的本质是Socket的读取,Socket在Linux系统被抽象为流,IO可以理解为对流的操作。Linux标准文件访问方式如下:


img

当发起一个read操作的时候,会经历2个阶段:

  1. 等待数据准备;
  2. 将数据从内核拷贝到进程中;

对于socket流也会经历两个阶段:

  1. 将磁盘或者其他设备到达以后的信息,拷贝到内核的缓存区中;
  2. 将内核的缓存区的数据复制到应用进程缓存中;

网络应用需要处理的无非就是两大类问题,网络IO,数据计算。相对于后者,网络IO的延迟,给应用带来的性能瓶颈大于后者,接下来我们介绍下IO模型:

同步阻塞IO(blocking IO)

同步阻塞 IO 模型是最常用的一个模型,也是最简单的模型。在Linux中,默认情况下所有的socket都是blocking。阻塞就是进程休息, CPU处理其它进程去了。

用户空间的应用程序执行一个系统调用(recvform),这会导致应用程序阻塞,直到数据准备好,并且将数据从内核复制到用户进程,最后进程再处理数据,在等待数据到处理数据的两个阶段,整个进程都被阻塞。不能处理别的网络IO。调用应用程序处于一种不再消费 CPU 而只是简单等待响应的状态,因此从处理的角度来看,这是非常有效的。在调用recv()/recvfrom()函数时,发生在内核中等待数据和复制数据的过程,大致如下图:


img
  1. 应用进程向内核发起recfrom读取数据;

  2. 准备数据报(应用进程阻塞);

  3. 将数据从内核负责到应用空间;

  4. 复制完成后,返回成功提示;

特点

同步阻塞 IO 整个过程都是阻塞的,对于用户可以及时返回数据,无延迟,对于开发者来说简单省事,对于系统来说无法应对高并发访问,以及用户在等待期间也无法进行其他任何操作。

同步非阻塞IO(nonblocking IO)

同步非阻塞就是采用轮询的方式,定时去查看数据是否准备完成。在这种模型中,进程是以非阻塞的形式打开的。IO 操作不会立即完成,如果该缓冲区没有数据的话,就会直接返回一个EWOULDBLOCK错误,不会让应用一直等待中。

非阻塞IO也会进行recvform系统调用,检查数据是否准备好,与阻塞IO不一样,非阻塞将大的整片时间的阻塞分成N多的小的阻塞, 所以进程不断地有机会被CPU访问。也就是说非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。


img
  1. 应用进程向内核发起recvfrom读取数据;

  2. 没有数据报准备好,即刻返回EWOULDBLOCK错误码;

  3. 应用进程向内核发起recvfrom读取数据;

  4. 已有数据包准备好就进行一下步骤,否则还是返回错误码;

  5. 将数据从内核拷贝到用户空间;

  6. 完成后,返回成功提示;

特点

同步非阻塞方式相比同步阻塞方式,在等待任务期间进程可以处理其他事情,缺点的话就是因为采用定时轮询的方式,导致系统整体的吞吐量降低。

IO多路复用( IO multiplexing)

同步非阻塞方式需要不断主动轮询,轮询占据了很大一部分过程,轮询会消耗大量的CPU时间,当并发情况下服务器很可能一瞬间会收到几十上百万的请求,这种情况下同步非阻塞IO需要创建几十上百万的线程去读取数据,同时又因为应用线程是不知道什么时候会有数据读取,为了保证消息能及时读取到,那么这些线程自己必须不断的向内核发送recvfrom 请求来读取数据。这么多的线程不断调用recvfrom 请求数据,明细是对线程资源的浪费。

于是有人就想到了由一个线程循环查询多个任务的完成状态(fd文件描述符),只要有任何一个任务完成,就去处理它。这样就可以只需要一个或几个线程就可以完成数据状态询问的操作,当有数据准备就绪之后再分配对应的线程去读取数据,这么做就可以节省出大量的线程资源出来,这个就是IO多路复用。


img
  1. 应用进程向内核发起select调用;

  2. kernel会监听所有select负责的socket;

  3. 任何一个socket中的数据准备好了,select就会返回;

  4. 应用进程再调用recvfrom操作,将数据从内核拷贝到用户空间;

  5. 完成后,返回成功提示;

特点

IO多路复用与同步非阻塞相比,应用线程通过调select/poll之后,阻塞住,进入到内核态后由内核线程来轮询这个应用线程所关注的所有文件描述符对应的缓冲区是否有数据准备就绪,只要有一个缓冲区数据准备就绪,就可以进行数据拷贝然后返回给用户线程,这种方式就减少了用户线程的不断轮询以及避免在每次轮询时所产生的两次上下文切换过程。

此外就是IO多路复用模型可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时(这里并不是全部数据可读或可写),才真正调用I/O操作函数。

此外还需要注意的是,IO多路复用既然可以处理多个IO,也就带来了新的问题,多个IO之间的顺序变得不确定了。

信号驱动IO(signal-driven IO)

IO多路复用解决了一个线程或者多个线程可以监控多个文件描述符的问题,但是select是采用轮询的方式来监控多个文件描述符的,通过不断的轮询文件描述符的可读状态来知道是否有可读的数据,这样无脑的轮询就显得有点浪费,因为大部分情况下的轮询都是无效的,于是乎有人就想,能不能不要总是去轮询数据是否准备就绪,能不能发出请求后,等数据准备好了在通知我,所以这样就出现了信号驱动IO。

信号驱动IO不是用循环请求询问的方式去监控数据就绪状态,而是在调用sigaction时候建立一个SIGIO的信号联系,当内核数据准备好之后再通过SIGIO信号,通知线程数据准备好后的可读状态,当线程收到可读状态的信号后,此时再向内核发起recvfrom读取数据的请求。因为信号驱动IO的模型下,应用线程在发出信号监控后即可返回,不会阻塞,所以这样的方式下,一个应用线程也可以同时监控多个文件描述符。


image.png
  1. 应用进程开启套接口信号驱动IO功能,通过系统调用sigaction执行一个信号处理函数,请求即刻返回;

  2. 当数据准备就绪时,就生成对应进程的SIGIO信号,通过信号回调通知应用进程;

  3. 应用进程再调用recvfrom操作,将数据从内核拷贝到用户空间;

  4. 完成后,返回成功提示;

特点

信号驱动IO相比于IO多路复用,在通过这种建立信号关联的方式,实现了发出请求后只需要等待数据就绪的通知即可,这样就可以避免大量无效的数据状态轮询操作。

异步非阻塞 IO(asynchronous IO)

不管是IO多路复用还是信号驱动,我们要读取数据的时候,总是要发起两阶段的请求,第一次发送select请求,询问数据状态是否准备好,第二次发送recevform请求读取数据。这个时候我们会有一个疑问,为什么在读数据之前总要有个数据就绪的状态,可不可以应用进程只需要向内核发送一个read 请求,告诉内核要读取数据后,就立即返回。当内核数据准备就绪,内核会主动把数据从内核复制到用户空间,等所有操作都完成之后,内核会发起一个通知告诉应用,所以这样就出现了异步非阻塞 IO模型。

异步非阻塞IO模型应用进程发起aio_read操作之后,立刻就可以开始去做其它的事。后续的操作有内核接管,当内核收到一个asynchronous read之后,它会立刻返回,不会对用户进程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成以后,内核会给用户进程发送一个signal或执行一个基于线程的回调函数来完成这次 IO 处理过程。


image.png
  1. 应用进程发起aio_read操作,立即返回;

  2. 内核等待数据准备完成,然后将数据拷贝到用户内存;

  3. 内核会给用户进程发送一个signal信号;

  4. 收到信号,返回成功提示;

特点

异步非阻塞 IO相比于信号驱动IO,信号驱动IO模型只是由内核通知我们可以开始下一个IO操作,而异步非阻塞 IO模型是由内核通知我们操作什么时候完成。

五种IO模型总结

阻塞IO和非阻塞IO区别

调用阻塞IO会一直阻塞住对应的进程直到操作完成,而非阻塞IO在内核还准备数据的情况下会立刻返回。

同步IO和异步IO区别

两者的区别就在于同步IO做IO操作的时候会将进程阻塞,也就是应用进程调用recvfrom操作,recvfrom会将数据从内核拷贝到用户内存中,在这段时间内,进程是被阻塞的。


img

举个例子

小王去买火车票,三天后买到一张退票。参演人员(老李,黄牛,售票员,快递员),往返车站耗费1小时。

同步阻塞 IO

小王去火车站买票,排队三天买到一张退票。整个三天小王无法做其他事情,只能做买票的一件事情。

同步非阻塞 IO

小王去火车站买票,隔一天去火车站问有没有退票,三天后买到一张票。整个过程中小王需要往返3次,往返消耗3小时,这个期间小王可以做其他事情。

IO多路复用
select/poll

小王去火车站买票,委托黄牛购买,然后每隔12小时打电话询问黄牛,黄牛三天买到票,然后小王去火车站交钱领票。整个小王需要往返2次,往返消耗2小时,黄牛需要手续费100,打电话6次,这里的黄牛就是select/poll,多路指的就是一个黄牛可以服务多个人。

epoll

小王去火车站买票,委托黄牛购买,黄牛买到后即通知小王去领,然后小王去火车站交钱领票。整个过程小王需要往返2次,往返消耗2小时,黄牛需要手续费100,无需打电话。

信号驱动IO

小王去火车站买票,售票员留下电话,有票后,售票员电话通知小王,然后小王去火车站交钱领票。整个过程小王需要往返2次,往返消耗2小时,无手续费,无需打电话。

异步非阻塞 IO

小王去火车站买票,给售票员留下电话,有票后,售票员电话通知小王并快递送票上门。整个过程小王需要往返1次,往返消耗1小时,无手续费,无需打电话。

参考

IO 多路复用是什么意思

100%弄明白5种IO模型

聊聊Linux 五种IO模型

结束

欢迎大家点点关注,点点赞!

聊聊同步、异步、阻塞、非阻塞以及IO模型的更多相关文章

  1. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  2. 高性能IO设计模式之阻塞/非阻塞,同步/异步解析

    提到高性能,我想大家都喜欢这个,今天我们就主要来弄明白在高性能的I/O设计中的几个关键概念,做任何事最重要的第一步就是要把概念弄的清晰无误不是么?在这里就是:阻塞,非阻塞,同步,异步. OK, 现在来 ...

  3. 操作系统介绍-操作系统历史,IO,进程的三态,同步异步阻塞非阻塞

    1.操作系统历史 2.进程,IO,同步异步阻塞非阻塞 操作系统历史: 手工操作: 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 手工操 ...

  4. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  5. 理解同步,异步,阻塞,非阻塞,多路复用,事件驱动IO

    以下是IO的一个基本过程 先理解一下用户空间和内核空间,系统为了保护内核数据,会将寻址空间分为用户空间和内核空间,32位机器为例,高1G字节作为内核空间,低3G字节作为用户空间.当用户程序读取数据的时 ...

  6. (转)同步异步,阻塞非阻塞 和nginx的IO模型

    同步异步,阻塞非阻塞 和nginx的IO模型  原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...

  7. Java IO 学习(一)同步/异步/阻塞/非阻塞

    关于IO,同步/异步/阻塞/非阻塞,这几个关键词是经常听到的,譬如: “Java oio是阻塞的,nio是非阻塞的” “NodeJS的IO是异步的” 但是这些东西听多了就容易迷糊,比方说同步是否就是阻 ...

  8. python并发编程之IO模型 同步 异步 阻塞 非阻塞

    IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...

  9. 关于IO的同步,异步,阻塞,非阻塞

    上次写了一篇文章:Unix IO 模型学习.恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现.中途正好讨论了网络IO的同步.异步.阻塞.非 ...

  10. 正确理解这四个重要且容易混乱的知识点:异步,同步,阻塞,非阻塞,5种IO模型

    本文讨论的背景是Linux环境下的network IO,同步IO和异步IO,阻塞IO和非阻塞IO分别是什么 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进 ...

随机推荐

  1. Nginx SERVER块配置

    1 Listen 指令 Example Configuration Directives 2 server_name指令 2.1 规则 指令后可以跟多个域名,第一个是主域名 *泛域名:进支持在最前或最 ...

  2. 『学了就忘』Linux系统管理 — 82、Linux中进程的查看(ps命令)

    目录 1.ps命令介绍 2.ps aux命令示例 3.ps -le命令示例 4.pstree命令 1.ps命令介绍 ps命令是用来静态显示系统中进程的命令. 不过这个命令有些特殊,它部分命令的选项前不 ...

  3. 拆分函数Splitter.Split…(Power Query 之 M 语言)

    按相同分隔符拆分: =Splitter.SplitTextByDelimiter("拆分符号", 引号字符) 拆分符号 直接输入 特殊符号 制表符:#(tab) 回车:#(cr) ...

  4. 估计工期标识(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 有时候吧,我们遇到的任务,工期并不是那么好定的,本来嘛,一个项目如果全靠拍脑袋,最后搞不好会被人锤脑袋-- 看来PM有风险 ...

  5. UVA10976 分数拆分 Fractions Again?! 题解

    Content 给定正整数 \(k\),找到所有的正整数 \(x \geqslant y\),使得 \(\frac{1}{k}=\frac{1}{x}+\frac{1}{y}\). 数据范围:\(0& ...

  6. LuoguP7071 [CSP-J2020] 优秀的拆分 题解

    Content 给定一个数 \(n\),求是否能够拆分成 \(2\) 的正整数次幂的和的形式,并给出具体方案. 数据范围:\(1\leqslant n\leqslant 10^7\). Solutio ...

  7. 介绍下Shell中的${}、##和%%使用范例,本文给出了不同情况下得到的结果。

    介绍下Shell中的${}.##和%%使用范例,本文给出了不同情况下得到的结果.假设定义了一个变量为:代码如下:file=/dir1/dir2/dir3/my.file.txt可以用${ }分别替换得 ...

  8. SQL注入绕过

    空格字符绕过 %09 TAB建(水平) %0a 新建一行,换行 %0b TAB建(垂直) %0c 新的一页 %0d return 功能 %a0 空格 %00 /**/ /*!*/./*!50009*/ ...

  9. 【蓝桥杯】非VIP基础题型训练17题 (Python 题解)

    NO.I 基础题型 基础练习汇总 时间 题目 解析 21.12.24 早上 1. A+B问题 练习系统的适应 21.12.24 早上 2. 数组排序 输入输出排序 21.12.24 早上 3. 十六进 ...

  10. Network (poj1144)

    A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting se ...