2020/01/06 03-Nginx和IO模型

提供httpd服务有很多软件可以选择,传统选择httpd,互联网公司nginx
2020/01/06 03-Nginx和IO模型
apache的性能不如nginx好,nginx擅长高并发,可以达到c10k,tengine是阿里的二次开发,但是这个只要改个源码即可

2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型
一些公司为了提高速度,购买了CDN服务

2020/01/06 03-Nginx和IO模型
httpd服务本来有三种工作模型2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型prefork,两级结构,一个主进程开启若干个子进程,每个子进程来响应用户请求2020/01/06 03-Nginx和IO模型
pstree可以看到工作关系
2020/01/06 03-Nginx和IO模型
master主进程是以root身份运行的,worker子进程是以apache身份运行的2020/01/06 03-Nginx和IO模型
**
worker是三级结构,主进程生成若干子进程,子进程生成多个线程,每个线程来响应用户请求
event是以worker类似,只不过增加了一个监控线程,来回收没有人访问的线程
apache再并发达到过万的时候,性能就受到影响**

做一个大页面
2020/01/06 03-Nginx和IO模型

测试一下,是否回打开100个进程响应请求
2020/01/06 03-Nginx和IO模型
可以看到有一个增长,但是还是太快了
2020/01/06 03-Nginx和IO模型
可以看到有大量的用户请求链接
2020/01/06 03-Nginx和IO模型
每打开一个用户链接,就会开启一个worker进程提供响应
2020/01/06 03-Nginx和IO模型
worker方式是以线程方式来提供服务
worker是三级结构,主进程生成若干子进程,子进程生成多个线程,每个线程来响应用户请求2020/01/06 03-Nginx和IO模型
修改apache配置文件即可实现
2020/01/06 03-Nginx和IO模型
默认prefork2020/01/06 03-Nginx和IO模型
启用下面的worker
2020/01/06 03-Nginx和IO模型
这样就修改工作模式
2020/01/06 03-Nginx和IO模型
主进程带若干子进程,子进程带多个线程2020/01/06 03-Nginx和IO模型
event是以worker类似,只不过增加了一个监控线程,来回收没有人访问的线程2020/01/06 03-Nginx和IO模型
httpd因为天生基于select的IO模型,导致并发连接数达不到理想状态,达到c10k很难上去了2020/01/06 03-Nginx和IO模型磁盘里的io
事实上,再对于网络中的应用来传输数据的时候,本质上也算是IO,因为在网络编程的时候,(http,python脚本程序,来实现socket通讯),网络通讯的时候也是经过读写机制的,只不过在经过网络的时候,是通过发到socket文件里去的,你发数据到远程主机,也是通过socket文件,对方也是通过socket来接收远程数据
网路也算是一种IO

2020/01/06 03-Nginx和IO模型
一个远程用户请求一个html文件,请求到达网卡,根据tcp/ip分层,是应该吧mac层,ip报头,传输层,tcp报文头部到达应用层,就到达了nginx进程(工作在用户空间,但是工作在用户空间的进程是不能直接访问硬件的(要想把文件返回给用户,就需要由内核来完成这个工作,内核才有权力去访问磁盘,磁盘把文件先返回给内核,有一个内核的缓冲区buffer,
再通过内核缓冲区把文件复制到应用程序nginx的缓冲区buffer,然后封装报文头部,再发送过去
进行了4个过程

2020/01/06 03-Nginx和IO模型
显然从磁盘上获取数据更久
内核空间,复制到nginx的内存空间,因为都是再内存里,所以速度是很快的
再快也比不上cpu,cpu是最快的,内存的数量再怎么着,也慢了一个数量级

PIO,应用程序的输入输出模型,所有数据经过CPU来转发,从磁盘把文件拷贝到cpu里,cpu再复制到内存中,所有的事情必须经过CPU,这样CPU会很繁忙,拖累整个服务器性能
2020/01/06 03-Nginx和IO模型
DMA就没有转发的过程了,直接发给内核空间的buff,对cpu来讲只要发个指令,硬件上有专门的设备DMAC,直接内存访问控制器,当磁盘文件想要读入到内存中,cpu只要发个指令即可,空闲的时候CPU就可以做其他事情了2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型*同步(synchhronous/异步(asynchronous, =====关注消息的通知机制
nginx的同步异步更关注的是消息通信机制
同步(synchhronous,调用者必须等待被调用者返回消息(调用者主动地去问被调用者是否完成,调用者消耗的尽力更多一些)
异步(asynchronous,被调用者发个消息给调用者,表达事情已经做完了,对于调用者来讲更加省心一点
*
2020/01/06 03-Nginx和IO模型阻塞和非阻塞的关注点在于 ,调用者发任务给被调用者之后,到底是干等着,还是去忙别的事情
如果是阻塞,就是当调用者发送任务给被调用者之后,傻等着,什么时候被调用者做完之后才能去做别的事情
非阻塞,当调用者发送一个任务给被调用者,被调用者在没有完成任务之前,调用者仍然可以做别的事情,可以不挂起,不傻等着

同步异步主要关注消息机制,如何知道被调用者完成了

**
同步阻塞,比较消耗精力,只能把事情一件件做完
同步非阻塞,虽然没有阻塞,但是因为是同步机制,就并没有很好地利用这个条件
异步阻塞,洗完了通过你,阻塞(还在等着它),实际上什么也做不了,只是在那里等待浪费资源
异步非阻塞,效率最好,把任务下达了,就可以该做什么就去做什么了**

2020/01/06 03-Nginx和IO模型
在生产中用到的IO模型,真正用到的有5种
2020/01/06 03-Nginx和IO模型当用户发起请求,用户进程希望得到一个数据(因为用户进程没有权限,就要去系统调用,内核中的API接口,让内核来帮忙完成),这时候有两个阶段,
第一阶段把数据从磁盘上把文件获取到内核空间,从内核复制到用户空间的缓存区中,这个就是对应画图的第4步
用户进程发送任务给内核之后,就一直在那里等待,同步阻塞,只能得到任务完成,最终得到数据
用户进程想要工作就需要把3,4步做完了,返回一个成功结果,这样用户进程得到数据了,就可以做别的事情去了,在这期间什么也做不了,是阻塞的状态

应用程序在得到数据之前,什么都做不了,只能等待,这样就造成了,应用程序给用户感觉是迟迟没有反应,并发效率很差
2020/01/06 03-Nginx和IO模型
访问一个应用程序,应用程序本身的效率高还是内核效率高,让你感受更快一些,一般来讲用户是访问应用程序不是去访问内核,内核是为应用程序提供服务的,所以相对来讲,应用程序反应的响应速度更快
如果应用程序干的活多了,负担较重,自然对于用户的响应就慢了
如果内核做的事情多了,就变相减轻了应用程序干的活

2020/01/06 03-Nginx和IO模型同步,意味做完了任务不通知你,只能自己去看
当需要一个资源,就发送请求,到内核,内核帮你完成,但是完成不完成不知道,就一次次地去询问
数据从磁盘放到内核的时候认为完成(实际上没做完,我们得到数据是需要在用户进程的内存空间里发送到用户)
在磁盘复制到用户空间的过程中,用户是并不了解的(会不断地去询问是否完成)
询问一次就要消耗CPU就做了很多无用功

同步非阻塞表面上不阻塞,但是其实跟阻塞差不多,阻塞还好点,非阻塞会一直询问,来回消耗资源,性能更差2020/01/06 03-Nginx和IO模型2020/01/06 03-Nginx和IO模型之前的是每个进程发送请求给系统调用,跑到内核,内核去磁盘上读取数据
每个进程都是直接去访问系统,调用获取数据的,这样对内核来讲,是直接和进程打交道的

不用跑腿,委托代理人即可
IO多路复用是专门找一个代理人叫select,(select相当于一个办事的大屏幕,当内核从磁盘拿到数据后,就通知某个用户进程,任务完成了)
在第一个阶段,用户的进程是阻塞在select这里的
后续的阶段,是用户进程需要等待数据从内核空间中复制到用户空间来完成的
实际上也是一种阻塞状态,只不过阻塞的位置和场景并不一样(阻塞在了select上,select接受了很多进程的调用,总代理)
select,利用IO多路复用,可以并发地响应用户请求,相当于专门的人接待客人,不用去和后面打交道

2020/01/06 03-Nginx和IO模型
虽然性能上没有提高,但是有专门的select模块,来并发响应用户请求
可以多路请求复用这个select(实际上并不是select才能实现这个功能,还有poll,也能使用系统调用功能,能够实现类似的功能
IO复用模型应用场景主要在如下环境中使用

2020/01/06 03-Nginx和IO模型
信号驱动IO模型,有些异步特性,调用者不需要主动去问被调用者,被调用者做完,主动通知你
内核从磁盘读取数据的时候,
第三个过程,还没得到数据,进程就可以做点别的事情,内核把数据准备好之后通知用户进程,
接下来,第4个状态
内核数据复制到用户进程中,这个过程用户进程是处于等待的
所以有一部分实现了异步,有一部分实现了同步

2020/01/06 03-Nginx和IO模型
2020/01/06 03-Nginx和IO模型
用户发起请求,用户进程,告诉内核需要数据,内核从磁盘获取数据,从内核空间把数复制到用户空间,这个用户程序一直在持续运行,一直没有阻塞,一直在忙自己的,所有的工作交由内核做
用户程序发些很不操心,内核做的事情较多一点,进程做的时候越少,同时就能响应更多用户请求

2020/01/06 03-Nginx和IO模型
windos的IIS底层调用的就是异步IO模型
2020/01/06 03-Nginx和IO模型1.同步一直在阻塞,什么时候内核把事情做完了,才能做其他的事情,同步阻塞模型
2.同步非阻塞模型,不是完全非阻塞,第三个简单不阻塞,但是同步,就需要不断地去询问是否完成
表明上不阻塞,其实还不如阻塞,第4阶段,什么时候把内核空间数据复制到用户进程空间,就算结束
3.IO多路复用模型,这两个阶段其实都是阻塞的,只不过对于前面的阶段,阻塞在select上面,把任务阻塞在select。其他进程不用直接联系内核(实际还是阻塞,无非是换个地方)
4.信号驱动模型,第三阶段不阻塞,可以做别的事情,相对来讲性能提高了,第4阶段阻塞,自己去吧内核空间数据复制到用户空间
linux用的时候IO复用,和信号驱动模型
5.最理想的异步模型, windows的IIS用的
越往左偏同步的,右边是异步
重点掌握同步,异步,阻塞,非阻塞

2020/01/06 03-Nginx和IO模型
select,poll,epoll.kqueue,/dev/poll/iocp,都是和IO复用相关的
其中select是跨平台的,linux,windows也是支持的,用的 IO复用模型
poll是改进版的select(可以理解为select和poll是一个级别的,没有什么根本性变化)
EPOll相对select和poll来讲有极大的提升,具用的是信号驱动IO模型的一些特性,性能就相对来讲是更好一点。
locp是windows实现的,用的是真正的异步模型

2020/01/06 03-Nginx和IO模型select,poll,epoll都可以面对多个用户并发请求,相当于一个代理人,手机很多 的用户请求过来,手机以后,它去帮你从内核到磁盘上得到数据,但是这个数据有没有准备好,是不一样的,select和poll用 的是遍历机制。select和poll相当于代理好多人的请求,有些用户数据准备好了,但是还有很多用户数据没有准备好,那就需要和进程用户打交道,并且告诉对方
(如何知道谁的进程准备好,select和poll是遍历的,就需要一个个去找,(比如用户询问,数据有没有好,你说等会,你需要去查,一个个去查,到最后结束告诉你结果,这样全表扫描,效率是偏低的))

**
epoll是异步的机制,就有信号驱动的一些特性,数据准备好后,会主动通知你去拿,相对来讲效率更高
select和poll
用户请求越多,遍历时间就越长
epol因为是回调机制,和你的请求个数是没有关系的
slect最大并发数是1000个,内核来决定的,poll和epoll是无上限的**
2020/01/06 03-Nginx和IO模型
时间复杂度 epoll是O(1)的
2020/01/06 03-Nginx和IO模型
EPOLL效率要更高2020/01/06 03-Nginx和IO模型
变相描述了select和poll,epoll
select最大并发1000,修改这个值只能重新编译内核 了
水平处罚
跨平台使用
poll
只支持linux
无限制并发
这两个都属于同步IO
epoll属于异步IO
支持水平触发和边缘触发
水平触发通知多次
边缘触发只通知一次
2020/01/06 03-Nginx和IO模型
每个进程能打开多少个文件
2020/01/06 03-Nginx和IO模型
2020/01/06 03-Nginx和IO模型

nginx也开始有商业化了,社区版和商业版
,org组织,.com商业公司
淘宝的Tengine,就是用nginx做的二次开发
openresty

2020/01/06 03-Nginx和IO模型
nginx是模块化的
2020/01/06 03-Nginx和IO模型