目录
引言
一、Nginx简介
二、Nginx工作场景
(一)Nginx的工作场景
(二)影响用户体验的因素
三、IO模型
(一)零拷贝技术
(二)IO模型的相关概念
(三)nginx实现方式
四、Nginx功能概述
(一)Nginx 功能介绍
(二)基础特性
(三)Web 服务相关的功能
(四)Nginx 进程结构
五、安装Nginx
(一)yum安装
(二)编译安装
1.安装软件
2.启动服务
3.创建自启文件
六、Nginx基本操作
(一)nginx命令
1.显示版本详细信息及模块
2.发送信号
3.指定配置
4.平滑升级
引言
Nginx(发音为“engine-x”)作为一款高性能的HTTP和反向代理服务器,以其稳定性、高并发处理能力和低资源消耗而广受赞誉。本文将带你走进Nginx的世界,从基础概念、安装部署,到核心功能详解和实战配置示例,助你全面掌握这款强大的Web服务器
一、Nginx简介
Nginx由俄罗斯开发者Igor Sysoev开发,最初于2004年发布,主要用于解决C10K问题(即同时处理上万个并发连接)。其设计目标是实现高并发、低延迟以及高效利用硬件资源。Nginx不仅是一个静态内容服务器,还支持动态脚本语言如PHP、Python等,并具备负载均衡、缓存、重写URL等功能。
二、Nginx工作场景
(一)Nginx的工作场景
正向代理: 代理的客户端
反向代理: 代理的服务端
(二)影响用户体验的因素
#客户端
客户端硬件配置
客户端网络速率
客户端与服务端距离#服务器
服务端网络速率
服务端硬件配置
服务端架构设计
服务端应用程序工作模式
服务端并发数量
服务端响应文件大小及数量 buffer cache
服务端I/O压力
三、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是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间
网络I/O : 一切皆文件,本质为对socket文件的读写 网络通信就是网络协议栈到用户空间进程的IO就是网络IO
第一步
#当用户发起http请求需要请求一个index.html网页文件客户端请求与服务器端建立连接,而后发送
#请求报文
第二步
#服务端的网卡收到请求报文,会将该报文复制到内核空间
第三步
#内核空间分析报文后交给对应的程序
第四步
#对应程序会分析该报文,将报文和自己的配置文件,一一比对,按照配置文件完成请求,分析后发现
#客户需要index.html,由于程序的权限问题,没有资格直接调用磁盘上的#文件,程序会再将这个请
#求,再次转发给内核,内核得到后请求,去磁盘上找文件,找到文件后,复制给程序
第五步
#程序会构建响应报文,构建好后再交给内核空间
第六步
#内核空间得到响应报文后,再交给网卡
第七步
#网卡发给客户
(一)零拷贝技术
可以发现,在程序处理请求时,需要来回的复制,耗费了一定的cpu资源,为了解决这个问题,就诞生了零拷贝技术
零拷贝(Zero-copy)是一种计算机技术,它允许数据在操作系统内核空间和硬件之间传输时不需要经过用户空间,从而避免了数据在内存中不必要的复制操作。这种技术显著提高了数据传输效率,减少了CPU使用率,并降低了延迟。
传统的数据传输过程通常涉及多次数据复制:磁盘到内核缓冲区、内核缓冲区到用户程序缓冲区、用户程序缓冲区到网络协议栈缓冲区等。
1.DMA(Direct Memory Access): 硬件可以直接访问内存,无需CPU参与数据搬运,例如从磁盘读取数据时,可以由硬盘控制器直接将数据写入内核缓冲区。
2.Mapped Buffers: 将内核缓冲区映射到用户空间,使得用户进程可以直接读写内核缓冲区,避免了数据在内核与用户空间之间的复制。
3.Sendfile系统调用: 在Linux系统中,sendfile系统调用可以直接将文件内容从内核缓冲区发送到网络设备的缓冲区,跳过了用户空间的中间环节。
在nginx的配置文件中,就开启了零拷贝技术
4.Scatter-Gather I/O: 支持将数据分散存放在多个不连续的缓冲区中,一次I/O操作可以处理多个缓冲区的数据传输,避免了将数据先合并再传输的过程
零拷贝技术广泛应用于高性能网络服务器、大数据处理、存储和数据库系统等领域,尤其对于需要频繁进行大块数据传输的应用来说,能够极大提升性能。
(二)IO模型的相关概念
同步/异步(消息反馈机制):关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
同步:应用程序发起一个I/O请求后,会一直等待该操作完成并返回结果。在此期间,程序会被阻塞,不能执行其他任务,直到操作系统通知该I/O操作已完成。
异步:应用程序发起一个I/O请求后,无需等待其完成,可以继续执行后续代码。当I/O操作完成后,操作系统通过回调函数、事件或信号等方式通知应用程序,此时程序再处理I/O操作的结果。
阻塞:在调用I/O操作时,如果数据尚未准备好(例如,从网络读取数据但缓冲区为空),调用线程或进程将被挂起,直到数据准备好或者超时发生。
非阻塞:非阻塞模式下,无论数据是否准备好,系统都会立即返回一个状态值,不会导致调用线程或进程暂停。若数据未准备好,则返回错误信息(如EAGAIN/EWOULDBLOCK等),应用程序需要再次尝试读取,而不是等待数据就绪。
结合上述两种属性,常见的I/O模型包括:
同步阻塞I/O:发起I/O操作时,线程会等待,并且在数据就绪前保持阻塞状态。
同步非阻塞I/O:发起I/O操作时,即使数据未准备好也会立刻返回,然后应用程序需要不断地轮询检查数据是否准备好了。
异步阻塞I/O(较少见,一般不会这么组合):在这种情况下,通常是指线程虽然阻塞,但是系统会在后台异步处理I/O请求,待完成后唤醒阻塞的线程。
异步非阻塞I/O:应用发起I/O请求后立即返回,不需要循环轮询,操作系统会在I/O操作完成后以某种方式通知应用程序
(三)nginx实现方式
Nginx支持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚至是不同的系统版本上面的实现方式不尽相同,主要有以下实现方式:
1.select
select 库是在 linux 和 windows 平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,是最早期的事件驱动模型。
POSIX所规定,目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,本质上是通过设置或者
检查存放fd标志位的数据结构来进行下一步处理
缺点
单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义
FD_SETSIZE,再重新编译内核实现,但是这样也会造成效率的降低
单个进程可监视的fd数量被限制,默认是1024,修改此值需要重新编译内核
对socket是线性扫描,即采用轮询的方法,效率较低
select 采取了内存拷贝方法来实现内核将 FD 消息通知给用户空间,这样一个用来存放大量fd的数据结
构,这样会使得用户空间和内核空间在传递该结构时复制开销大
2.poll
在Linux 的基本驱动模型,windows 不支持此驱动模型,是 selec t的升级版,取消了最大的并发限制,在编译 nginx 的时候可以使用 --with-poll_module 和 --without-poll_module 这两个指定是否编译select库。
本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态
其没有最大连接数的限制,原因是它是基于链表来存储的
大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
poll特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
select是边缘触发即只通知一次
3.epoll
epoll 库是 Nginx 服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和 select 和 poll 有很大的区别,epoll 是 poll 的升级版,但是与 poll 有很大的区别。
epoll 的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候再去轮训检查这个表,以判断事件是否发生,epoll 支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时 epoll 库的 I/O 效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作
在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减少复制开销
三者之间的区别
select | poll | epoll | |
操作方式 | 遍历 | 遍历 | 回调 |
底层实现 | 数组 | 链表 | 哈希表 |
IO效率 | 每次调用都进行线性遍历,时间复杂度为O(n) | 同左 | 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪的fd放到rdlist里,时间复杂度O(1) |
最大连接数 | 1024(x86)/2048(x64) | 无上限 | 无上限 |
fd拷贝 | 每次调用select都需要把f集合从 用户拷贝到内核态 | 每次调用poll,都需要把fd集合从用户态拷贝到内核态 | 调用epoll ctl时拷贝进内核并保存,之后每次epoll wait不拷贝 |
在Linux系统中,nginx默认使用的是epoll,而windows系统不支持epoll
四、Nginx功能概述
(一)Nginx 功能介绍
-
静态的web资源服务器html,图片,js,css,txt等静态资源
-
http/https协议的反向代理 ,7层 url
-
结合FastCGI /uWSGI/SCGI等协议反向代理动态资源请求
-
tcp/udp协议的请求转发(反向代理) 4层
(二)基础特性
-
模块化设计,较好的扩展性
-
高可靠性
-
支持热部署:不停机更新配置文件,升级版本,更换日志文件
-
低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
-
event-driven, aio, mmap,sendfile
(三)Web 服务相关的功能
-
虚拟主机(server)
-
支持 keep-alive 和管道连接(利用一个连接做多次请求)
-
访问日志(支持基于日志缓冲提高其性能)
-
url rewirte
-
路径别名
-
基于IP及用户的访问控制
-
支持速率限制及并发数限制
-
重新配置和在线升级而无须中断客户的工作进程
(四)Nginx 进程结构
web请求处理机制
-
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。
-
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
主进程(master process)的功能:
对外接口:接收外部的操作(信号) 对内转发:根据外部的操作的不同,通过信号管理 Worker 监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程 读取Nginx 配置文件并验证其有效性和正确性 建立、绑定和关闭socket连接 按照配置生成、管理和结束工作进程 接受外界指令,比如重启、升级及退出服务器等指令 不中断服务,实现平滑升级,重启服务并应用新的配置 开启日志文件,获取文件描述符 不中断服务,实现平滑升级,升级失败进行回滚处理 编译和处理perl脚本
工作进程(worker process)的功能:
所有 Worker 进程都是平等的 实际处理:网络请求,由 Worker 进程处理 Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争CPU资源, 增加上下文切换的损耗 接受处理客户的请求 将请求依次送入各个功能模块进行处理 I/O调用,获取响应数据 与后端服务器通信,接收后端服务器的处理结果 缓存数据,访问缓存索引,查询和调用缓存数据 发送请求结果,响应客户的请求 接收主程序指令,比如重启、升级和退出等
五、安装Nginx
(一)yum安装
yum安装nginx需要先安装epel源,而后再进行安装
yum install epel-release.noarch -y ;yum install nginx -y
或者配置yum仓库,从官方源或其它可靠源下载
(二)编译安装
1.安装软件
yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel
#安装依赖包
useradd -M -u 80 -s /sbin/nologin nginx
#新建nginx用户便于管理
cd /data
wget http://nginx.org/download/nginx-1.18.0.tar.gz
#官网下载安装包
tar xf nginx-1.18.0.tar.gz
cd nginx-1.18.0/
#解压软件包
mkdir /apps/nginx -p #新建一个安装目录
./configure --help
#查看帮助模块
./configure --prefix=/apps/nginx
#指定软件的安装路径
安装完成后会生成在这个路径下,将会创建包括sbin/(存放可执行文件)、conf/(存放配置文件)、lofs/(存放日志文件)等在内的标准目录结构
1.conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有个样板配置文件,是文件名.default结尾,使用的使用将其复制为并将default去掉即可。
2.html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面。
3.logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比如/var/logs/nginx里面。
4.sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
make &&make install
#编译源代码并安装
chown -R nginx.nginx /apps/nginx
#修改权限
2.启动服务
安装完成后可以使用绝对路径启动
使用killall nginx来关闭服务
也可以通过创建软链接来启动服务
3.创建自启文件
在/usr/lib/systemd/system/目录下创建一个以.service结尾的文件,将nginx服务交给system服务管理
vim /usr/lib/systemd/system/nginx.service
在文件中添加以下内容
先使用killall nginx将服务关闭
systemctl daemon-reload
#重新加载配置
systemctl enable --now nginx
#开机自启并立即启动
六、Nginx基本操作
(一)nginx命令
nginx 命令支持向其发送信号,实现不同功能
nginx 当做单独命令使用有以下选项
-? 或 -h:#显示帮助信息,列出所有可用的命令行选项。
-v #显示Nginx版本号并退出。
-V:#不仅显示版本号,还会展示编译时指定的所有配置选项,这对于了解服务器的#具体构建情况非常有用。
-t:#测试当前的Nginx配置文件是否正确,如果配置没有语法错误,会输出 "nginx: #the configuration file /path/to/nginx.conf syntax is ok" 并退出。#否则将显示错误信息。
-T:#与 -t 类似,但还会把解析后的配置结构以树状形式详细打印出来。
-q:#在使用 -t 或 -T 选项测试配置时,抑制非错误消息,只显示错误信息。
-s signal:#向Nginx主进程发送信号,signal可以是stop(停止服务)、quit(优雅#地关闭服务)、reopen(重新打开日志文件,通常用于日志切割操作)、#reload(重载配置文件)等。
-p prefix:#设置Nginx安装目录前缀,默认为 /apps/nginx/,此路径下包含了可执行文件#、配置文件、日志文件等。
-c filename:#指定要使用的配置文件路径,默认为 conf/nginx.conf。
-g directives:#设置全局指令,这些指令通常会在配置文件之外定义,可以在启动时直接应#用到Nginx进程中。
1.显示版本详细信息及模块
可以在安装之后再重新添加模块
使用./configure 需要添加的模块
./configure --prefix=/apps/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
下载完毕之后重新编译与安装
make && make install
而后重新服务:systemctl restart nginx
2.发送信号
使用man手册可以查看支持的信号
直接使用man无法查看,需要使用绝对/相对路径查看
SIGINT , SIGTERM,stop | 这两个信号都会使Nginx快速关闭,即立即停止服务。在接收到这些信号后,Nginx会 尽可能快地结束所有工作进程。 |
SIGHUP,reload | 当Nginx接收到SIGHUP信号时,它会重新加载配置文件,并启动一个新的工作进程 来使用新的配置信息。同时,旧的工作进程会在完成当前请求后被优雅地关闭,从而实 现配置的平滑更新而不会中断现有的连接。 |
SIGQUIT,quit | 此信号会让Nginx进行优雅的关闭,这意味着Nginx将等待所有已接受的请求处理完 毕后再停止服务。 |
SIGUSR1,reopen | 对于主进程和工作进程,发送SIGUSR1信号会使它们重新打开日志文件。通常在需 要重置或滚动日志文件时使用这个信号。 |
SIGUSR2 | 发送SIGUSR2信号给Nginx主进程时,可以实现在运行时升级Nginx可执行文件。这 意味着可以在不完全停止服务的情况下替换新编译的Nginx二进制文件并启动新的工 作进程,而旧的工作进程将在适当的时候被替换掉。 |
SIGWINCH | SIGWINCH信号会导致Nginx优雅地关闭工作进程。尽管这个信号在终端尺寸改变时 常见(窗口大小更改),但在Nginx中,它的作用也是让工作进程有序地退出。 |
例如:
nginx -s stop #立即关闭nginx
nginx -s quit #优雅退出 不影响业务的状态下退出
nginx -s reload #重新加载
USR1日志分割
USR1=reopen
在客户端访问后,日志文件会放到安装目录下的logs目录下的日志文件当中
access.log存放的是正常访问的日志
error.log存放的是错误日志
将原本的日志文件进行备份,并存放到存放日志信息的目录下,并新建一个日志
此时并没有完成,继续访问的话,还会存放在之前的文件中
因为nginx服务,并不知道修改了文件,需要发送信号去进行告知
可以通过nginx -s reopen 或者kill -s USR1 主进程号去进行告知
可以通过脚本搭配crontab定时任务去进行日志分割
3.指定配置
使用-g指令,指定配置信息
指定运行用户
在安装nginx时,默认运行用户是nginx用户
可以指定运行的用户
如果是以system开启的,先将它关闭,而后用nginx命令开启,并指定用户为kysw
nginx -g 'user kysw;'
4.平滑升级
nginx1.18.0 ----------->nginx1.20.2
首先准备好新的版本
执行make命令进行翻译,不需要执行make install
在升级之前查看进程,可以看到有一个master主进程和一个worker工作进程
①将旧Nginx文件换成新Nginx文件(注意备份)
此时,其它主机访问时,版本还是1.18,因为内存中执行的还是旧版本
②向master进程发送USR2信号
③master进程用新Nginx文件启动新master进程,系统中将有新旧两个Nginx主进程共同提供Web服务
④master进程修改pid文件名,加后缀.oldbin
这时候可以发现会将旧的PID文件名后面加上后缀.oldbin
⑤向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止,并删除Nginx.pid.oldbin文件
在此过程中,并不会影响老用户的体验
首先在/apps/nginx/html/目录(站点目录)下建立一个大文件
在客户端下载该文件
此时,去向老版本的主进程PID发送WINCH信号,并不会影响老用户的操作,而是等操作完成后再退出,而新用户访问则直接访问新版的nginx
kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`
#优雅关闭老进程的 worker 进程
⑥向旧master进程发送QUIT信号,关闭老master
⑦如果发现升级有问题,不要执行第六条,向老版本的master发送QUIT信号,可以回滚向老master发送HUP,向新master发送QUIT,关闭新版本的master进程