I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指的是在单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。
一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换过程,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说一次I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中的整个过程。
每次IO,都要经由两个阶段:
第一步:将数据从磁盘文件先加载至内核内存空间(缓冲区),此步骤需要等待数据准备完成,时间较长
第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短
2.系统IO模型
2.1 同步/异步:
同步:进程发出请求调用后,内核不提供通知机制,即文件IO处理完成后不通知进程,需要进程自己去问内核是否处理完成。
异步:进程发出请求调用后,内核会在调用处理完成后返回调用结果给进程,Nginx是异步的。
2.2 阻塞/非阻塞
阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成,最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
3.网络IO模型
阻塞型、非阻塞型、复用型、信号驱动型、异步
3.1 同步阻塞型IO模型(blocking IO)
程序向内核发送IO请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求(阻塞),并由进程轮训查看IO是否完成(同步),完成后进程将IO结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看IO是否完成,这种方式简单,但是比较慢,用的比较少。
3.2 同步非阻塞型I/O模型(nonblocking IO)
应用进程向内核发送请IO求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待(第一阶段非阻塞),而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核IO是否完成(同步)。
3.3 IO多路复用型(IO multiplexing)
IO multiplexing就是我们说的select,poll,epoll,有些地方也称这种IO方式为event driven IO(事件驱动IO),select/poll/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select,poll,epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程(异步),用户进程再调用read操作,将数据从kernel拷贝到用户进程。 当用户进程调用了select,那么整个进程会被block(阻塞)。
Apache prefork是此模式的主进程+多进程/单线程+select,work是主进程+多进程/多线程+poll模式
3.4 信号驱动式IO(signal-driven IO)
信号驱动IO:signal-driven I/O 用户进程可以通过sigaction系统调用注册一个信号处理程序,然后进程可以继续向下执行(非阻塞),当有IO操作准备就绪时,由内核通知触发一个SIGIO信号(异步)处理程序执行,用户进程再调用read操作,将数据从kernel拷贝到用户进程(阻塞), 此模型的优势在于等待数据报到达期间进程不被阻塞,进程可以继续执行,只要等待来自信号处理函数的通知,但是数据从内核空间拷贝到用户空间期间进程是阻塞的。
apache event模型就是主进程+多进程/多线程+信号驱动
3.5 异步(非阻塞) IO(asynchronous IO)
相对于同步IO,异步IO不是顺序执行,用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户进程可以去做别的事情(非阻塞),等到socket数据准备好了,内核直接复制数据给进程(非阻塞),然后从内核向进程发送通知(异步),异步非阻塞IO的两个阶段,进程都是非阻塞的。nginx就是异步非阻塞模型,并且使用epoll通知机制。
4.IO对比
这五种网络 I/O 模型中,越往后,阻塞越少,理论上效率也是越优。前四种在I/O操作第二阶段都有阻塞,因为recvfrom将阻塞进程/线程,只有第五种 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。
5.常用模型通知对比
水平触发-- 多次通知,需要关心数据是否取完,即数据取走之后即不再通知进程,以避免重复多次无效通知,通知效率较低。
边缘触发-- 一次通知,需要关心数据是否取走,即只通知一次怎么保证数据被进程成功取走了,以避免数据丢失,通知效率较高。
epoll优点:
没有最大并发连接的限制:能打开的FD的上限远大于1024(1G的内存能监听约10万个端口),具体查看/proc/sys/fs/file-max,此值和系统内存大小相关;
效率提升:非轮询的方式,不会随着FD数目的增加而效率下降,只有活跃可用的FD才会调用callback函数,即epoll最大的优点就在于它只管理“活跃”的连接,而跟连接总数无关;
内存拷贝,利用mmap(Memory Mapping)加速与内核空间的消息传递;即epoll使用mmap减少复制开销。
Nginx实现基于域名pc端和移动端
新建一个PC web站点
server {
listen 80 default_server;
server_name www.devops.com;
location / {
root /data/nginx/html/pc;
index index.html index.htm;
if ($http_user_agent ~* (mobile|iphone|ipad|android)) {
rewrite ^(.*)$ http://mobie.devops.com$1 permanent;
}
}
error_page 500 502 503 504 404 /error.html;
location = /error.html {
root html;
}
}
新建一个Mobile web站点
server {
listen 80;
server_name mobile.devops.com;
location / {
root /data/nginx/html/mobile;
index index.html index.htm;
if ($http_user_agent !~* (mobile|iphone|ipad|android)) {
rewrite ^(.*)$ http://www.devops.com$1 permanent;
}
}
error_page 500 502 503 504 404 /error.html;
location = /error.html {
root html;
}
}