Nginx之1基础篇

⼀:Web服务基础介绍:

1.1Apache prefork模型:

预派生模式一个主控制进程—生成—>多个子进程

使用select模型,最大并发1024

每个子进程有一个独立的线程响应用户请求,相对比较占用内存,但比较稳定,可以设置最大和最小进程数

最古老的一种模式,最稳定的模式---->适合于访问量不大的场景

优点稳定

缺点大量用户访问慢,占用资源,1024个进程不适合高并发场景

nginx平替产品_多线程

1.2Apache worker模型:

一种多进程和多线程混合的模型

有一个控制进程,启动多个控制子进程

每个子进程里面包含固定的线程,使用线程来处理请求

当线程不够使用的时候会再启动一个新的子进程,然后再进程里面再启动一个线程处理请求

由于其使用了线程处理请求,因此可承受更高的并发

优点:相比prefork占用的内存较少,可以同时处理更多的请求

缺点:使用keepalive的长连接方式,某个线程会一直被占用—>即使没有传输数据,也要一直等到超时才会被释放---->过多的线程被占据话导致在高并发场景下的无服务线程可用(该问题在prefork模式下一样)

nginx平替产品_python_02

1.3Apache event模型:

属于事件驱动模式(epoll)

和worker模式相近,最大区别在于,解决可keepalive场景下,长期被占用的线程的资源浪费问题---->某些线程因keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时

event MPM中,会有一个专门的线程开管理这些keepalive类型的线程

当有真实请求过来时---->将请求传递给服务线程---->执行完毕后,允许它释放---->(增强可高并发场景下的请求处理能力)

优点单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来时,将请求传递给服务线程,执行完毕后,允许它释放

缺点没有线程安全控制

nginx平替产品_linux_03

二、应用程序工作模式(Apache HTTP Server与Nginx的工作模式):

2.1Centos安装Apache:
#Centos 7.x⽬前默认为prefork模式,ubuntu 18.04已经使⽤event模式
Apache线程验证⽅式:
[root@localhost ~]# httpd -V #Centos系统
AH00558: httpd: Could not reliably determine the server's fully qualified
domain name, using localhost.localdomain. Set the 'ServerName' directive
globally to suppress this message
Server version: Apache/2.4.6 (CentOS)
Server built: Aug 8 2019 11:41:18
Server's Module Magic Number: 20120211:24
Server loaded: APR 1.4.8, APR-UTIL 1.5.2
Compiled using: APR 1.4.8, APR-UTIL 1.5.2
Architecture: 64-bit
Server MPM: prefork #MPM模式为prefork
 threaded: no
2.2Ubuntu 18安装Apache:

Ubuntu 18.04.3系统:

root@mq-node1:~# apachectl -V
Server version: Apache/2.4.29 (Ubuntu)
Server built: 2019-09-16T12:58:48
Server's Module Magic Number: 20120211:68
Server loaded: APR 1.6.3, APR-UTIL 1.6.1
Compiled using: APR 1.6.3, APR-UTIL 1.6.1
Architecture: 64-bit
Server MPM: event #MPM模式为event
 threaded: yes (fixed thread count)
 forked: yes (variable process count)
2.3:Nginx默认模式:

**Nginx(Master+Worker)**模式:

单个主进程+多个工作进程,每个工作进程中一个线程处理客服端的请求

2.4:服务端I/O:

IOPS(Input/Output Per Second)即每秒的输入输出量(或读写次数)---->衡量磁盘性能的主要指标之一

一次I/O把数据从内核空间中的内存数据—复制—>用户空间中进程的内存当中的整个过程

网络通信是从将网络协议栈到用户空间进程的IO—>(网络IO)

每次IO都经由两个阶段:

  • 将数据从磁盘文件—加载至—>内核空间(缓存区),此步徐等待数据准备完成,时间较长
  • 将数据从内核缓冲区---->复制到用户空间的进程的内存中,时间较短

三、系统I/O模型:

3.1同步/异步:

同步:进程发出请求调用内核不提供通知机制---->文件IO处理完成后不通知进程,需要进程自己去问内核是否处理完成

异步:进程发出请求调用后,内核会在调用处理完成后返回调用结果给进程,(Nginx是异步)

nginx平替产品_多线程_04

3.2:阻塞/非阻塞:

关注调用者在等待结果返回之前所处的状态

阻塞:blocking,指IO操作需要彻底完成后返回到用户空间,调用返回之前,调用者被挂起,干不了别的事情
非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成,最终的调用结果返回值之前,调用者不会被挂起,可做别的事情

nginx平替产品_内核_05

四、⽹络I/O模型:

阻塞型、非阻塞型、复用型、信号驱动型,异步

4.1:同步阻塞IO模型(blocking IO):

阻塞IO模型

优点程序简单,在阻塞等待数据期间进程挂起,基本不会占用CPU资源

缺点每个连接需要独立的进程单独处理,当并发请求量大时为了维护程序、内存、进程切换开销较大(apache的prefork使用该模式)

同步阻塞:

程序向内核发送IO请求后⼀直等待内核响应

如果内核处理请求的IO操作不能立即返回

进程⼀直等待并不再接受新的请求

并由进程轮训查看IO是否完成完成后进程将IO结果返回给Client

在IO没有返回期间进程不能接受其他客户的请求,⽽且是有进程⾃⼰去查看IO是否完成。

nginx平替产品_多线程_06

4.2:同步非阻塞型I/O模型(nonblocking IO):

同步⾮阻塞:

应⽤进程向内核发送请IO求后⼀直等待内核响应

如果内核处理请求的IO操作不能⽴即返回IO结果

进程将不再等待,⽽且继续处理其他请求

但是仍然需要进程隔⼀段时间就要查看内核IO是否完成

nginx平替产品_linux_07

4.3:IO多路复用(IO multiplexing):

IO multiplexing就是我们说的select,有些地⽅也称这种IO⽅式为event driven IO(事件驱动IO)

select/poll/epoll的好处—>单个process可以同时处理多个网络连接的IO

(Apache prefork是此模式的主进程+多进程/单线程+select,worker是主进程+多进程/多线程+poll模 式)

⽤户进程调⽤了select,那么整个进程会被block

⽽同时,kernel会“监视”所有select负责的socket

任何⼀个socket中的数据准备好了,select就会返回,这个时候⽤户进程再调⽤read操作

将数据从kernel拷⻉到⽤户进程

nginx平替产品_内核_08

4.4:信号驱动式IO(signal-driven IO):

优点:进程没有在等待数据时被阻塞,内核直接返回调用接受信号—>不影响进程继续处理其他请求因此可提高资源的利用率

缺点信号I/O在大量IO操作时可能因信号队列溢出导致无法通知

信号驱动IO:进程向内核发送IO调用后,不再等待内核响应,可继续接受其他请求,内核收到进程请求后进行的IO 如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程,(apache event模型就是主进程+多进程+信号驱动)

nginx平替产品_多线程_09

4.5:异步(非阻塞)IO(asynchronous IO):

异步非阻塞:

程序进程向内核发送IO调用后,不用等待内核响应,可继续接受其他请求

内核调用的IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核

内核在将IO完成的结果返回、给进程,期间进程可以接受新的请求内

核也可以处理新的事物,因此相互不影响,可实现较大的同时并实现较高的IO复用,(nginx是异步非阻塞模型)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tAvHMZJO-1616504667810)(E:\Linux笔记资料\nginx\asynchronousIO.jpg)]

4.6:IO对比:

真正的 I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SqeG0GBj-1616504667812)(E:\Linux笔记资料\nginx\recvfrom.jpg)]

4.7:常用模型汇总:

\

select

poll

epoll

操作方式

遍历

遍历

回调

底层实现

数组

链表

哈希表

IO效率

每次调用都进行线性遍历,时间复杂度为O(n)

每次调用都进行线性遍历,时间复杂度为O(n)

时间通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到rdllist里面,时间复杂度为O(1)

最大连接数

1024(x86)或2048(x64)

无上限

无上限

fd拷贝

每次调用select都需要把fd集合从用户态拷贝到内核态

每次调用poll,都需要把fd集合从用户态拷贝到内核态

调用epoll_ctl时拷贝进内核并保存,之后每次epoll_wait不拷贝

4.8:常用模型通知对比:

⽔平触发– 多次通知,需要关心数据是否取完,即数据取走之后即不再通知进程,以避免重复多次⽆效通

知,通知效率较低。

边缘触发– ⼀次通知,需要关心数据是否取走,即只通知⼀次怎么保证数据被进程成功取走了,以避免数据丢失,通知效率较高

nginx平替产品_nginx平替产品_10

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减少复制开销
4.9:MMAP介绍:

MMAP(memeory mapping,文件映射),系统调用---->使进程之间通过映射同一个普通文件实现共享内存,普通文件被映射到进程地址空间后,进程可以像访问普通文件一样对文件进行访问------>

目的

  • 性能提升:进程可直接访问映射到内存的文件---->再需要从内核内存空间copy到进程空间再操作,省略一次copy
  • 进程间文件共享:多个进程可访问一份映射到内存的文件---->多个请求同一文件的请求直接读映射文件并返回给客服端
4.10:传统方式copy数据:

nginx平替产品_多线程_11

4.11:MMAP方式:

mmap可将磁盘文件映射到内存中,直接操作内存Linux内核将负责同步内存和磁盘文件中的数据

nginx平替产品_内核_12