一、 Linux常见的IO模型
I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。
一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中。
Linux的I/O分类:
- 磁盘I/O
- 网络I/O
1. I/O模型相关概念
同步/异步(消息反馈机制):关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
2. 磁盘I/O
(本地ip)磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间
零拷贝技术
传统的 Linux 系统的标准 I/O 接口(read、write)是基于数据拷贝的,也就是数据都是 copy_to_user 或者 copy_from_user,这样做的好处是,通过中间缓存的机制,减少磁盘 I/O 的操作,但是坏处也很明显,大量数据的拷贝,用户态和内核态的频繁切换,会消耗大量的 CPU 资源,严重影响数据传输的性能。
零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解 CPU 的压力。零拷贝并没有真正做到"0"拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化
3. 网络I/O
一切皆文件,本质为对socket文件的读写 (在进程的fd文件夹下形成了一个临时文件来存储这次访问的基本信息)
3.1 阻塞型I/O模型(blocking IO)
- 优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
- 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较大,apache 的preforck使用的是这种模式。
3.2 非阻塞型I/O模型 (nonblocking IO)
非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完成。
3.3 多路复用I/O模型 (I/O multiplexing)
I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。
3.4 信号驱动式I/O模型 (signal-driven IO)
- 优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率
- 缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
3.5 异步I/O模型 (asynchronous IO)
异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知我们何时开始一个I/O操作,而异步I/O是由内核通知我们I/O操作何时完成。
3.6 总结
这五种 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步 I/O,因为其中真正的I/O 操作(recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。
Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统版本上面的实现方式不尽相同,主要有以下实现方式:
js
1、select:
select库是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部
分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
2、poll:
在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编
译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select
库。
3、epoll:
epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和
select和poll有很大的区别,epoll是poll的升级版,但是与poll有很大的区别.
epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个
表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大
数,同时epoll库的I/O效率不随描述符数目增加而线性下降,因为它只会对内核上报的"活跃"的描述符进行操作。
4、rtsig:
5、kqueue:
6、/dev/poll:
7、eventport:
8、Iocp:
二、 Nginx 概述
Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器,而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。
基础特性:
- 模块化设计,较好的扩展性
- 高可靠性
- 支持热部署:不停机更新配置文件,升级版本,更换日志文件
- 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
Nginx架构: master + work
- master process:主进程(守护进程),用来管理工作进程。
- worker process:工作进程,用来处理用户的请求。
注意: Apache和Nginx的默认端口都是80,如果其中一个已经启动了,那么再启动另一个会报错。如果想要同时使用,可以修改其中一个的端口号。
三、 Nginx 模块
- 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能
- 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如:端口配置、网页编码设置、HTTP响应头设置等等
- 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如:Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、安全协议 SSL 支持等
- 邮件服务模块:主要用于支持 Nginx 的邮件服务,包括对 POP3 协议、IMAP 协议和 SMTP协议的支持
- Stream服务模块: 实现反向代理功能,包括TCP协议代理 反向
- 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等
js
`常用模块:`
ngx_http_core_module 核心模块
ngx_http_access_module 访问控制
ngx_http_auth_basic_module 身份验证
ngx_http_gzip_module 压缩模块
ngx_http_1og_module 日志模块
ngx_http_proxy_module 代理模块
ngx_http_rewrite_module 重写模块
ngx_http_stub_status_module 状态页模块
ngx_http_upstream_module 反向代理
ngx_http_stream_module 四层代理
四、 安装及使用Nginx
1. 编译安装nginx
- 关闭防火墙,安装依赖包,新建nginx用户便于管理;
js
[root@node1 ~]# systemctl stop firewalld
[root@node1 ~]# setenforce 0
[root@node1 ~]# yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel
[root@node1 ~]# useradd -M -s /sbin/nologin nginx
//nginx服务程序默认以nobody身份运行,建议为其创建专门的用户账号,以便更准确地控制其访问权限。
- 官网下载安装包,并解压;
js
[root@node1 ~]# cd /opt/
[root@node1 opt]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@node1 opt]# tar xf nginx-1.18.0.tar.gz
- 编译安装;
js
[root@node1 opt]# cd nginx-1.18.0/
[root@node1 nginx-1.18.0]# ./configure
> --prefix=/apps/nginx \ //指定nginx的安装路径
> --user=nginx \ //指定用户名(运行用户)
> --group=nginx \ //指定组名
> --with-http_ssl_module \
> --with-http_v2_module \
> --with-http_realip_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --with-pcre \
> --with-stream \
> --with-stream_ssl_module \
> --with-stream_realip_module
[root@node1 nginx-1.18.0]# make -j2 && make install
[root@node1 nginx-1.18.0]# chown -R nginx.nginx /apps/nginx
- 创建软连接;
js
[root@node1 nginx-1.18.0]# ln -s /apps/nginx/sbin/nginx /usr/sbin/
//将nginx的可执行文件做个软链接,放入环境变量PATH的目录下,让系统识别nginx的操作指令
- 创建 Nginx 自启动文件。
js
[root@node1 nginx-1.18.0]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
#注意文件位置,如果不对 启动不了
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
#注意启动文件位置
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
[root@node1 nginx-1.18.0]# systemctl daemon-reload //重新加载服务
[root@node1 nginx-1.18.0]# chown -R nginx.nginx /apps/nginx //修改权限
2. yum安装
centos7 需要安装epel源
js
yum install -y epel-release //安装epel源
yum install nginx -y //yum安装nginx
3. 命令、信号使用
nginx可以作为单独的命令使用,有以下选项:
选项 | 含义 |
---|---|
-t | 检查语法 |
-T | 检查语法,并打印所有配置 |
-v | 显示版本 |
-V | 显示详细信息,包括编译的信息 |
-c | 指定配置文件启动 |
-s | 发送信号=kill |
nginx 命令支持向其发送信号,实现不同功能 nginx -s signal
命令 | 等同于 | 含义 |
---|---|---|
nginx -s reload | kill -HUP | 重新加载配置文件 |
nginx -s stop | kill -9(KILL) | 立即停止 |
nginx -s quit | kill -3(QUIT) | 优雅的退出 |
nginx -s reopen | kill -USR1 | 重新生成日志文件 |
nginx -s USR2 | / | 飞行中升级 |