Nginx之1基础篇
⼀:Web服务基础介绍:
1.1Apache prefork模型:
预派生模式, 一个主控制进程—生成—>多个子进程
使用select模型,最大并发1024
每个子进程有一个独立的线程响应用户请求,相对比较占用内存,但比较稳定,可以设置最大和最小进程数
最古老的一种模式,最稳定的模式---->适合于访问量不大的场景
优点:稳定
缺点:大量用户访问慢,占用资源,1024个进程不适合高并发场景
1.2Apache worker模型:
一种多进程和多线程混合的模型
有一个控制进程,启动多个控制子进程
每个子进程里面包含固定的线程,使用线程来处理请求
当线程不够使用的时候会再启动一个新的子进程,然后再进程里面再启动一个线程处理请求
由于其使用了线程处理请求,因此可承受更高的并发
优点:相比prefork占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占用—>即使没有传输数据,也要一直等到超时才会被释放---->过多的线程被占据话导致在高并发场景下的无服务线程可用(该问题在prefork模式下一样)
1.3Apache event模型:
属于事件驱动模式(epoll)
和worker模式相近,最大区别在于,解决可keepalive场景下,长期被占用的线程的资源浪费问题---->某些线程因keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时
event MPM中,会有一个专门的线程开管理这些keepalive类型的线程
当有真实请求过来时---->将请求传递给服务线程---->执行完毕后,允许它释放---->(增强可高并发场景下的请求处理能力)
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当有真实请求过来时,将请求传递给服务线程,执行完毕后,允许它释放
缺点:没有线程安全控制
二、应用程序工作模式(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是异步)
3.2:阻塞/非阻塞:
关注调用者在等待结果返回之前所处的状态
阻塞:blocking,指IO操作需要彻底完成后返回到用户空间,调用返回之前,调用者被挂起,干不了别的事情
非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成,最终的调用结果返回值之前,调用者不会被挂起,可做别的事情
四、⽹络I/O模型:
阻塞型、非阻塞型、复用型、信号驱动型,异步
4.1:同步阻塞IO模型(blocking IO):
阻塞IO模型
优点:程序简单,在阻塞等待数据期间进程挂起,基本不会占用CPU资源
缺点:每个连接需要独立的进程单独处理,当并发请求量大时为了维护程序、内存、进程切换开销较大(apache的prefork使用该模式)
同步阻塞:
程序向内核发送IO请求后⼀直等待内核响应
如果内核处理请求的IO操作不能立即返回
则进程将⼀直等待并不再接受新的请求
并由进程轮训查看IO是否完成,完成后进程将IO结果返回给Client
在IO没有返回期间进程不能接受其他客户的请求,⽽且是有进程⾃⼰去查看IO是否完成。
4.2:同步非阻塞型I/O模型(nonblocking IO):
同步⾮阻塞:
应⽤进程向内核发送请IO求后⼀直等待内核响应
如果内核处理请求的IO操作不能⽴即返回IO结果
进程将不再等待,⽽且继续处理其他请求
但是仍然需要进程隔⼀段时间就要查看内核IO是否完成。
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拷⻉到⽤户进程。
4.4:信号驱动式IO(signal-driven IO):
优点:进程没有在等待数据时被阻塞,内核直接返回调用接受信号—>不影响进程继续处理其他请求因此可提高资源的利用率
缺点:信号I/O在大量IO操作时可能因信号队列溢出导致无法通知
信号驱动IO:进程向内核发送IO调用后,不再等待内核响应,可继续接受其他请求,内核收到进程请求后进行的IO 如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程,(apache event模型就是主进程+多进程+信号驱动)
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:常用模型通知对比:
⽔平触发– 多次通知,需要关心数据是否取完,即数据取走之后即不再通知进程,以避免重复多次⽆效通
知,通知效率较低。
边缘触发– ⼀次通知,需要关心数据是否取走,即只通知⼀次怎么保证数据被进程成功取走了,以避免数据丢失,通知效率较高
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数据:
4.11:MMAP方式:
mmap可将磁盘文件映射到内存中,直接操作内存Linux内核将负责同步内存和磁盘文件中的数据