linux高阶-Nginx服务(一)-模型详解

应用程序的工作模式

httpd MPM(Multi-Processing Module,多进程处理模块)模式:
prefork:进程模型,两级结构,主进程master负责⽣成⼦进程,每个⼦进程负责响应⼀个请求
worker:线程模型,三级结构,主进程master负责⽣成⼦进程,每个⼦进程负责⽣成多个线程,每个线程响应⼀个请
求
event:线程模型,三级结构,主进程master负责⽣成⼦进程,每个⼦进程⽣成多个线程,每个线程响应⼀个请求,但
是增加了⼀个监听线程,⽤于解决在设置了keep-alived场景下线程的空等待问题。
Nginx(Master+Worker)模式:
主进程
⼯作进程 #直接处理客⼾的请求

//线程验证⽅式
cat /proc/PID/status
pstree -p PID

服务端I/O

  • I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输⼊输出量(或读写次数),是衡量磁盘性能的主要指标之⼀。IOPS是指的是在单位时间内系统能处理的I/O请求数量,⼀般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。
机械磁盘的寻道时间、旋转延迟和数据传输时间:
寻道时间:是指磁头移动到正确的磁道上所花费的时间,寻道时间越短则I/O处理就越快,⽬前磁盘的寻道时间⼀般在
3-15毫秒左右。
旋转延迟:是指将磁盘⽚旋转到数据所在的扇区到磁头下⾯所花费的时间,旋转延迟取决于磁盘的转速,通常使⽤磁盘
旋转⼀周所需要时间的1/2之⼀表⽰,⽐如7200转的磁盘平均训传延迟⼤约为60*1000/7200/2=4.17毫秒,公式的意
思为 (每分钟60秒*1000毫秒每秒/7200转每分钟/2),如果是15000转的则为60*1000/15000/2=2毫秒。
数据传输时间:指的是读取到数据后传输数据的时间,主要取决于传输速率,这个值等于数据⼤⼩除以传输速率,⽬前
的磁盘接⼝每秒的传输速度可以达到600MB,因此可以忽略不计。
常⻅的机械磁盘平均寻道时间值:
7200转/分的磁盘平均物理寻道时间:9毫秒
10000转/分的磁盘平均物理寻道时间:6毫秒
15000转/分的磁盘平均物理寻道时间:4毫秒
常⻅磁盘的平均延迟时间:
7200转的机械盘平均延迟:60*1000/7200/2 = 4.17ms
10000转的机械盘平均延迟:60*1000/10000/2 = 3ms
15000转的机械盘平均延迟:60*1000/15000/2 = 2ms
每秒最⼤IOPS的计算⽅法:
7200转的磁盘IOPS计算⽅式:1000毫秒/(9毫秒的寻道时间+4.17毫秒的平均旋转延迟时间)=1000/13.13=75.9
IOPS
10000转的磁盘的IOPS计算⽅式:1000毫秒/(6毫秒的寻道时间+3毫秒的平均旋转延迟时间)=1000/9=111 IOPS
15000转的磁盘的IOPS计算⽅式:15000毫秒/(4毫秒的寻道时间+2毫秒的平均旋转延迟时间)=1000/6=166.6
IOPS
  • ⼀次完整的I/O是⽤⼾空间的进程数据与内核空间的内核数据的报⽂的完整交换,但是由于内核空间与⽤⼾空间是严格隔离的,所以其数据交换过程中不能由⽤⼾空间的进程直接调⽤内核空间的内存数据,⽽是需要经历⼀次从内核空间中的内存数据copy到⽤⼾空间的进程内存当中,所以简单说I/O就是把数据从内核空间中的内存数据复制到⽤⼾空间中进程的内存当中。
  • ⽽⽹络通信就是⽹络协议栈到⽤⼾空间进程的IO就是⽹络IO

在这里插入图片描述

  • 磁盘I/O是进程向内核发起系统调⽤,请求磁盘上的某个资源⽐如是⽂件或者是图⽚,然后内核通过相应的驱动程序将⽬标图⽚加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是⽐较⼤的数据也需要等待时间。
每次IO,都要经由两个阶段:
第⼀步:将数据从磁盘⽂件先加载⾄内核内存空间(缓冲区),此步骤需要等待数据准备完成,时间较⻓
第⼆步:将数据从内核缓冲区复制到⽤⼾空间的进程的内存中,时间较短

系统I/O模型

同步/异步:关注的是事件处理的消息通信机制,即在等待⼀件事情的处理结果时,被调⽤者是否提供完成通知。

  • 同步:synchronous,调⽤者等待被调⽤者返回消息后才能继续执⾏,如果被调⽤者不提供消息返回则为同步,同步需要调⽤者主动询问事情是否处理完成。
  • 异步:asynchronous,被调⽤者通过状态、通知或回调机制主动通知调⽤者被调⽤者的运⾏状态。
同步:进程发出请求调⽤后,等内核返回响应以后才继续下⼀个请求,即如果内核⼀直不返回数据,那么进程就⼀直等。
异步:进程发出请求调⽤后,不等内核返回响应,接着处理下⼀个请求,Nginx是异步的。

阻塞/⾮阻塞:关注调⽤者在等待结果返回之前所处的状态

  • 阻塞:blocking,指IO操作需要彻底完成后才返回到⽤⼾空间,调⽤结果返回之前,调⽤者被挂起,⼲不了别的事情。
  • ⾮阻塞:nonblocking,指IO操作被调⽤后⽴即返回给⽤⼾⼀个状态值,⽆需等到IO操作彻底完成,最终的调⽤结果返回之前,调⽤者不会被挂起,可以去做别的事情。

网络I/O模型

  • 网络I/O模型可分为:阻塞型、非阻塞型、复用型、信号驱动型、异步型(其中前四个被称为同步IO)
  • 任何I/O过程中都包含两个步骤:第一是等待;第二时拷贝。在实际的应用场景中等待消耗的时间往往都会高于拷贝的时间,所以让I/O更高效的最核心办法就是缩短等待的时间。
  • 到底什么是IO?我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢?拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目的是把它读取到内存中。可以把这个步骤简化成把数据从硬件(硬盘)中读取到用户空间中。其实真正的文件读取还涉及到缓存等细节,这里就不展开讲述了。

1.阻塞I/O模型(blocking I/O)

  • 我们钓鱼的时候,有一种方式比较惬意,比较轻松,那就是我们坐在鱼竿面前,这个过程中我们什么也不做,双手一直把着鱼竿,就静静的等着鱼儿咬钩。一旦手上感受到鱼的力道,就把鱼钓起来放入鱼篓中。然后再钓下一条鱼。
  • 映射到Linux操作系统中,这就是一种最简单的IO模型,即阻塞IO。 阻塞 I/O 是最简单的 I/O 模型,一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。

在这里插入图片描述

  • 应用进程通过系统调用 recvfrom 接收数据,但由于内核还未准备好数据报,应用进程就会阻塞住,直到内核准备好数据报,recvfrom 完成数据报复制工作,应用进程才能结束阻塞状态。

  • 这种钓鱼方式相对来说比较简单,对于钓鱼的人来说,不需要什么特制的鱼竿,拿一根够长的木棍就可以悠闲的开始钓鱼了(实现简单)。缺点就是比较耗费时间,比较适合那种对鱼的需求量小的情况(并发低,时效性要求低)。

2.非阻塞I/O模型(noblocking I/O)

  • 我们钓鱼的时候,在等待鱼儿咬钩的过程中,我们可以做点别的事情,比如玩一把王者荣耀、看一集《延禧攻略》等等。但是,我们要时不时的去看一下鱼竿,一旦发现有鱼儿上钩了,就把鱼钓上来。
  • 映射到Linux操作系统中,这就是非阻塞的IO模型。应用进程与内核交互,目的未达到之前,不再一味的等着,而是直接返回。然后通过轮询的方式,不停的去问内核数据准备有没有准备好。如果某一次轮询发现数据已经准备好了,那就把数据拷贝到用户空间中。

在这里插入图片描述

  • 应用进程通过 recvfrom 调用不停的去和内核交互,直到内核准备好数据。如果没有准备好,内核会返回error,应用进程在得到error后,过一段时间再发送recvfrom请求。在两次发送请求的时间段,进程可以先做别的事情。这种方式钓鱼,和阻塞IO比,所使用的工具没有什么变化,但是钓鱼的时候可以做些其他事情,增加时间的利用率。

  • 注意:非阻塞IO往往需要程序员以循环的方式反复尝试读写文件描述符,这个过程称为轮询。这个过程对CPU来说是较大的浪费,一般只有在特定的场景下才使用

3.信号驱动I/O模型(signal blocking I/O)

  • 我们钓鱼的时候,为了避免自己一遍一遍的去查看鱼竿,我们可以给鱼竿安装一个报警器。当有鱼儿咬钩的时候立刻报警。然后我们再收到报警后,去把鱼钓起来。
  • 映射到Linux操作系统中,这就是信号驱动IO。应用进程在读取文件时通知内核,如果某个 socket 的某个事件发生时,请向我发一个信号。在收到信号后,信号对应的处理函数会进行后续处理。

在这里插入图片描述

  • 内核将数据准备好的时候,使用SIGIO信号通知应用程序进行IO操作。 信号驱动,内核是在数据准备好之后通知进程,然后进程再通过recvfrom操作进行数据拷贝。我们可以认为数据准备阶段是异步的,但是,数据拷贝操作是同步的。所以,整个IO过程也不能认为是异步的。

  • 可以这样理解。我们把钓鱼过程,可以拆分为两个步骤:1、鱼咬钩(数据准备)。2、把鱼钓起来放进鱼篓里(数据拷贝)。无论以上提到的哪种钓鱼方式,在第二步,都是需要人主动去做的,并不是鱼竿自己完成的。所以,这个钓鱼过程其实还是同步进行的。

4.I/O复用模型(I/O multiplexing)

  • 我们钓鱼的时候,为了保证可以最短的时间钓到最多的鱼,我们同一时间摆放多个鱼竿,同时钓鱼。然后哪个鱼竿有鱼儿咬钩了,我们就把哪个鱼竿上面的鱼钓起来。
  • 映射到Linux操作系统中,这就是IO复用模型。多个进程的IO可以注册到同一个管道上,这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中。

在这里插入图片描述

  • IO复用模型是多了一个select函数,多个进程的IO可以注册到同一个select上,当用户进程调用该select,select会监听所有注册好的IO,如果所有被监听的IO需要的数据都没有准备好时,select调用进程会阻塞。当任意一个IO所需的数据准备好之后,select调用就会返回,然后进程在通过recvfrom来进行数据拷贝

  • 这里的IO复用模型,并没有向内核注册信号处理函数,所以,他也属于阻塞型。进程在发出select后,要等到select监听的所有IO操作中至少有一个需要的数据准备好,才会有返回,并且也需要再次发送请求去进行文件的拷贝。这种方式的钓鱼,通过增加鱼竿的方式,可以有效的提升效率。

5. 异步I/O模型(asynchronous I/O)

  • 我们钓鱼的时候,采用一种高科技钓鱼竿,即全自动钓鱼竿。可以自动感应鱼上钩,自动收竿,更厉害的可以自动把鱼放进鱼篓里。然后,通知我们鱼已经钓到了,他就继续去钓下一条鱼去了。这种方式的钓鱼,无疑是最省事儿的。啥都不需要管,只需要交给鱼竿就可以了。
  • 映射到Linux操作系统中,这就是异步IO模型。应用进程把IO请求传给内核后,完全由内核去操作文件拷贝。内核完成相关操作后,会发信号告诉应用进程本次IO已经完成。

在这里插入图片描述

  • 用户进程发起aio_read操作之后,给内核传递描述符、缓冲区指针、缓冲区大小等,告诉内核当整个操作完成时,如何通知进程,然后就立刻去做其他事情了。当内核收到aio_read后,会立刻返回,然后内核开始等待数据准备,数据准备好以后,直接把数据拷贝到用户控件,然后再通知进程本次IO已经完成。

五种I/O对比

在这里插入图片描述

  • 这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步I/O,因为其中真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配

实现方式

  • Select:Linux实现对应,I/O复用模型,BSD4.2最早实现,POSIX标准,一般
    操作系统均有实现
  • Poll:Linux实现,对应I/O复用模型,System V unix最早实现
  • Epoll:Linux特有,对应I/O复用模型,具有信号驱动I/O模型的某些特性
  • Kqueue:FreeBSD实现,对应I/O复用模型,具有信号驱动I/O模型某些特性
  • /dev/poll:SUN的Solaris实现,对应I/O复用模型,具有信号驱动I/O模型的某些特性
  • Iocp Windows实现,对应第5种(异步I/O)模型

在这里插入图片描述

select

  • POSIX所规定,目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理

缺点

  • 单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义FD_SETSIZE,再重新编译内核实现,但是这样也会造成效率的降低
  • 单个进程可监视的fd数量被限制,默认是1024,修改此值需要重新编译内核
  • 对socket是线性扫描,即采用轮询的方法,效率较低
  • select 采取了内存拷贝方法来实现内核将 FD 消息通知给用户空间,这样一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大

poll

  • 本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态
  • 其没有最大连接数的限制,原因是它是基于链表来存储的
  • 大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
  • poll特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
  • 边缘触发:只通知一次

epoll

  • 在Linux 2.6内核中提出的select和poll的增强版本
  • 支持水平触发LT和边缘触发ET,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,并且只会通知一次
  • 使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知

优点

  • 没有最大并发连接的限制:能打开的FD的上限远大于1024(1G的内存能监听约10万个端口),具体查看/proc/sys/fs/file-max,此值和系统内存大小相关
  • 效率提升:非轮询的方式,不会随着FD数目的增加而效率下降;只有活跃可用的FD才会调用callback函数,即epoll最大的优点就在于它只管理“活跃”的连接,而跟连接总数无关
  • 内存拷贝,利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减少复制开销
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值