Nginx相关知识
目录
一.HTTP请求数据在服务器中的传输与处理详解
1.2 套字节
1.3 零拷贝技术
二.I/O模型
2.1 I/O模型简介
2.2 常见的I/O模型及其特点
1.同步/异步
2.阻塞vs 非阻塞
3. 同步/异步与阻塞/非阻塞的关系
4.多路复用I/O模型
5.异步I/O模型
三.Nginx模块
3.1 概述nginx
3.2 nginx配置文件
3.2.1 Nginx的配置文件的组成部分
3.2.2 主配置文件 (nginx.conf)核心结构
3.2.3 子配置文件 (conf.d/*.conf)
3.2.4 两者的关系
四.Nginx的安装
4.1 yum安装
4.2 编译安装
4.3 nginx开机自启
五.Nginx相关命令
5.1 nginx常见命令
5.2 Nginx的信号
六. Nginx运维三部曲:日志分割、无缝升级与版本回滚实战
6.1 分割日志
6.2 升级nginx
6.2.1升级思路
6.2.2 平滑升级nginx
6.3 回滚(退回旧版本)
一.HTTP请求数据在服务器中的传输与处理详解
1. 客户端发送数据
-
客户端(如浏览器)通过HTTP请求向服务器发送数据。
-
数据被打包成TCP/IP协议的数据包,通过网络传输到服务器的网卡。
2. 网卡接收数据
-
服务器的网卡接收到客户端发送的数据包。
-
网卡通过DMA(Direct Memory Access,直接内存访问)技术,将数据包直接写入内核空间的内存缓冲区,而不需要CPU的干预。
3. 数据进入内核空间
-
数据包被写入内核空间的接收缓冲区(Receive Buffer)。
-
内核的网络协议栈(如TCP/IP协议栈)对数据包进行解析,包括:
-
检查数据包的完整性(如校验和)。
-
解析IP头和TCP头,确定数据包的目标端口和应用程序。
-
4. 数据从内核空间到用户空间
-
内核将解析后的数据从接收缓冲区复制到用户空间的应用程序缓冲区(Application Buffer)。
-
这个过程通常通过系统调用(如
read
或recv
)完成。
5. 应用程序处理数据
-
应用程序(如Nginx)从用户空间的缓冲区中读取数据。
-
应用程序根据业务逻辑处理数据,例如:
-
解析HTTP请求。
-
生成HTTP响应。
-
将响应数据写入用户空间的发送缓冲区。
-
6. 数据从用户空间到内核空间
-
应用程序通过系统调用(如
write
或send
)将响应数据从用户空间的发送缓冲区复制到内核空间的发送缓冲区(Send Buffer)。
7. 数据从内核空间到网卡
-
内核的网络协议栈将发送缓冲区的数据打包成TCP/IP协议的数据包。
-
内核通过DMA技术将数据包从发送缓冲区直接传输到网卡。
8. 网卡发送数据
-
网卡将数据包发送到网络中,传输回客户端。
1.2 套字节
套接字(Socket)是网络编程中的一种抽象概念,用于实现不同主机之间的通信。通过套接字,应用程序可以在网络上进行数据传输,支持 TCP、UDP 等多种协议。
套字节的组成:
IP 地址和端口号
- IP 地址用于标识网络中的主机。
- 端口号用于标识主机上的具体应用程序
1.3 零拷贝技术
从"HTTP请求数据在服务器中的传输与处理"的过程可以看出在传统的 I/O 操作中,数据通常需要在用户空间和内核空间之间多次复制,而零拷贝(Zero-Copy)旨在减少数据在内存中的复制次数,从而提高数据传输的效率。
零拷贝技术的工作原理
零拷贝技术通过以下方式避免数据在内存中的多次复制:
- 直接内存访问(DMA):
- 使用 DMA 技术,数据可以直接从磁盘读取到内核缓冲区,无需 CPU 参与。
- 内存映射(mmap):
- 将内核缓冲区映射到用户空间,用户程序可以直接访问内核缓冲区,无需将数据复制到用户空间。
- sendfile 系统调用:
- 在 Linux 中,
sendfile
系统调用可以直接将数据从文件描述符传输到网络套接字,无需经过用户空间
- 在 Linux 中,
二.I/O模型
2.1 I/O模型简介
I/O模型(Input/Output Model)是计算机系统中用于处理输入输出操作的一种机制,它决定了程序如何与外部设备(如磁盘、网络、键盘等)进行数据交互。不同的I/O模型对程序的性能、并发能力和资源消耗有重要影响。
2.2 常见的I/O模型及其特点
1.同步/异步
程序执行流程是否需要等待操作完成。
同步:程序发起一个操作后,必须等待该操作完成才能继续执行后续代码。
异步:程序发起一个操作后,不需要等待操作完成,可以继续执行其他任务。操作完成后,系统会通知程序进行处理。
2.阻塞vs 非阻塞
线程是否会被挂起等待操作完成。
阻塞:当程序发起一个操作时,如果操作不能立即完成,线程会被挂起,直到操作完成。
非阻塞:当程序发起一个操作时,如果操作不能立即完成,会立即返回一个错误或状态,线程可以继续执行其他任务。
3. 同步/异步与阻塞/非阻塞的关系
-
同步阻塞:程序发起操作后,必须等待操作完成,线程会被挂起。
-
同步非阻塞:程序发起操作后,如果操作不能立即完成,会立即返回,程序需要轮询检查操作状态。
-
异步阻塞:这种组合在实际中很少见,因为异步操作通常是非阻塞的。
-
异步非阻塞:程序发起操作后,不需要等待操作完成,可以继续执行其他任务。操作完成后,系统会通知程序进行处理。
4.多路复用I/O模型
特点:单线程监控多个I/O操作:使用一个线程同时监控多个文件描述符(如Socket),当某个文件描述符就绪时,通知程序进行处理。
优点:高效处理大量并发连接,减少线程数量,节省资源。
缺点:不同操作系统的实现方式不同(如epoll
仅适用于Linux)。
常见的多路复用I/O模型有:
select
:- 支持的文件描述符数量有限(通常为1024),效率较低。
- 需要遍历所有文件描述符来找到准备就绪的 I/O 操作,时间复杂度为O(n)。
poll
:- 解决了
select
的文件描述符数量限制,但效率仍然不高。 - 同样需要遍历所有文件描述符,时间复杂度为O(n)。
- 解决了
epoll
(Linux特有):- 高效支持大量文件描述符,时间复杂度为O(1)。
- 使用事件通知机制,只处理就绪的文件描述符。
5.异步I/O模型
特点:
- 完全非阻塞:
- 程序发起I/O操作后,不需要等待操作完成,可以继续执行其他任务。
- 事件通知:
- I/O操作完成后,系统会通过回调函数或信号通知程序进行处理。
- 高效利用资源:
- 避免了线程阻塞,能够充分利用CPU和内存资源
三.Nginx模块
3.1 概述nginx
NGINX(发音为“engine-x”)是一个高性能的 Web服务器、反向代理服务器 和 负载均衡器。
主要功能包括:
静态内容服务
-
高效处理HTML、CSS、JS、图片等静态文件
-
支持sendfile零拷贝技术,大幅提升文件传输效率
动态内容处理:通过FastCGI支持PHP、Python等动态语言
负载均衡:支持HTTP、TCP/UDP负载均衡
补充:在Nginx中,支持HTTP负载均衡和TCP/UDP负载均衡分别对应应用层(L7)和传输层(L4)的流量分发能力,两者的核心区别在于协议栈层级和功能特性。
nginx的基础特性包括:
-
模块化设计,较好的扩展性
-
高可靠性
-
支持热部署:不停机更新配置文件,升级版本,更换日志文件
-
低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
-
event-driven, aio, mmap,sendfile
3.2 nginx配置文件
3.2.1 Nginx的配置文件的组成部分
主配置文件:nginx.conf
子配置文件: include conf.d/*.conf
3.2.2 主配置文件 (nginx.conf)核心结构
# 全局上下文 (Main Context)
user nginx;
worker_processes auto;# 事件驱动配置 (Events Context)
events {worker_connections 1024;
}# HTTP核心配置 (HTTP Context)
http {include /etc/nginx/mime.types;default_type application/octet-stream;# 包含子配置文件include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;
}# 流代理配置 (Stream Context)
stream {include /etc/nginx/stream.d/*.conf;
}
3.2.3 子配置文件 (conf.d/*.conf)
子配置文件一般在主配置文件的http部分
http块中可以包含多个子配置文件,常见的子配置文件
- HTTP 块 是 Nginx 配置的核心部分,包含
server
块、location
块、upstream
块等。 - Server 块 定义虚拟主机,包含
location
块。 - Location 块 定义 URL 路径的处理规则。
- Upstream 块 定义负载均衡的后端服务器组。
- Include 指令 用于引入子配置文件,实现配置文件的模块化。
3.2.4 两者的关系
Nginx 的主配置文件(nginx.conf
)和子配置文件(如 conf.d/*.conf
)之间是 分层包含关系,通过模块化设计实现配置的灵活管理。
四.Nginx的安装
4.1 yum安装
1.配置好基础仓库后# 2. 安装EPEL仓库
yum install -y epel-release# 3. 安装nginx
yum install -y nginx# 4. 启动nginx
systemctl start nginx
4.2 编译安装
准备工作
#安装依赖包
yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel
#新建nginx用户便于管理
useradd -M -s /sbin/nologin nginx
#官网下载包
wget http://nginx.org/download/nginx-1.18.0.tar.gz
开始编译
tar xf nginx-1.18.0.tar.gz
mkdir /apps/nginx -p
cd nginx-1.18.0/ #解压源码包./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 -j2 && make install #编译并安装chown -R nginx.nginx /apps/nginx #加权限ln -s /apps/nginx/sbin/nginx /usr/sbin/ #直接启动 不需要绝对路径ll /apps/nginx/ #检查该路径下是否存在安装的文件ls -l /apps/nginx/sbin/nginx #如果有 nginx 可执行文件,说明编译成功。/apps/nginx/sbin/nginx -v #如果返回类似 nginx version: nginx/1.18.0,说明安装成功。/apps/nginx/sbin/nginx #启动 Nginxps -ef | grep nginx #如果看到 master 和 worker 进程,说明 Nginx 已运行。
4.3 nginx开机自启
创建nginx自启文件
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
#注意启动文件位置
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID[Install]
WantedBy=multi-user.target
重新加载文件,启动
systemctl daemon-reload
#重新加载配置
systemctl enable --now nginx
#开机自启并立即启动 如果logs下有nginx.pid文件那会启动失败,只需删除logs下的nginx.pid即可。chown -R nginx.nginx /apps/nginx
#修改权限
systemctl is-enabled nginx#如果输出 enabled,表示 Nginx 已成功设置为开机自启
补充:之后的学习中,会遇到在一台服务器上运行多个 Nginx 实例的情况为避免 PID 冲突,所有实例都会尝试使用同一个 pid
文件路径。
###如果需要修改pid文件可以执行以下操作#################
mkdir /apps/nginx/run/
#创建目录
vim /apps/nginx/conf/nginx.conf
#修改配置文件
pid /apps/nginx/run/nginx.pid;
#找到 pid的位置修改
五.Nginx相关命令
5.1 nginx常见命令
#基本格式
nginx [选项] [参数]
选项 | 功能描述 |
---|---|
-c <配置文件> | 指定自定义的配置文件路径。 |
-t | 测试配置文件语法是否正确。 |
-T | 测试配置文件并打印解析后的配置内容。 |
-q | 在测试配置文件时以静默模式运行,只输出关键信息。 |
-g <全局配置> | 在命令行中指定全局配置选项。 |
-e <错误日志文件> | 设置错误日志文件的路径。 |
-s <信号> | 向 Nginx 发送信号(如 stop 、reload )。 |
-s <文件> | 启动 Nginx 并将 master 进程的 PID 写入指定文件。 |
-p <工作目录> | 设置工作目录,用于存放日志文件和临时文件。 |
-V | 显示 Nginx 的版本、编译信息和配置参数。 |
-h | 显示帮助信息,包括所有可用的命令行选项。 |
-q <文件> | 在测试配置文件时,将输出结果写入指定文件 |
5.2 Nginx的信号
Nginx 的信号(Signals)是用于控制 Nginx 进程行为的机制。通过向 Nginx 的 master 进程发送不同的信号,可以实现停止、重启、重新加载配置等操作。
#基本格式
nginx -s 信号
信号 | 功能描述 | 使用方式 |
---|---|---|
stop | 立即停止 Nginx 进程。 | nginx -s stop 或 kill -TERM <pid> |
quit | 优雅地停止 Nginx 进程。 | nginx -s quit 或 kill -QUIT <pid> |
reload | 重新加载配置文件。 | nginx -s reload 或 kill -HUP <pid> |
reopen | 重新打开日志文件。 | nginx -s reopen 或 kill -USR1 <pid> |
USR2 | 热升级 Nginx 可执行文件。 | kill -USR2 <pid> |
WINCH | 优雅地关闭旧的 worker 进程(热升级后使用)。 | kill -WINCH <pid> |
TERM/INT | 立即停止 Nginx 进程。 | kill -TERM <pid> 或 kill -INT <pid> |
HUP | 重新加载配置文件。 | kill -HUP <pid> |
六. Nginx运维三部曲:日志分割、无缝升级与版本回滚实战
6.1 分割日志
为什么需要分割日志?
-
文件过大:单个日志文件过大可能导致磁盘空间不足或日志分析工具无法处理。
-
归档管理:按时间或大小分割日志,便于归档、备份和清理。
-
性能优化:避免日志文件过大影响 Nginx 的性能。
cd /apps/nginx/logs# 1. 备份旧日志(保留原权限)
mv --backup=numbered --preserve=all access.log access.log.bak# 2. 创建新日志并设置正确权限
touch access.log
chown nginx:nginx access.log access.log.bak error.log # 同时修正所有日志权限
chmod 644 access.log access.log.bak error.log# 3. 通知 Nginx 重新打开日志
nginx -s reopen 2>/dev/null || kill -USR1 $(cat nginx.pid 2>/dev/null)# 4. 验证结果
ls -lh access.log* error.log*
6.2 升级nginx
6.2.1升级思路
-
将旧Nginx文件换成新Nginx文件(注意备份)
-
向master进程发送USR2信号
-
master进程修改pid文件名,加后缀.oldbin
-
master进程用新Nginx文件启动新master进程,系统中将有新旧两个Nginx主进程共同提供Web服务
-
向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止,并删除Nginx.pid.oldbin文件
-
向旧master进程发送QUIT信号,关闭老master
-
如果发现升级有问题,可以回滚向老master发送HUP,向新master发送QUIT
6.2.2 平滑升级nginx
Nginx 的平滑升级是指在不停机的情况下,将 Nginx 从旧版本升级到新版本。这样可以确保服务不中断,用户体验不受影响。
从nginx1.18升级到nginx1.20
#关闭防火墙
systemctl stop firewalld
setenforce 0
#启动服务
systemctl start nginx
#下载安装包到src目录
wget https://nginx.org/download/nginx-1.20.2.tar.gz -P /usr/local/src/cd /usr/local/src/;ls
tar xf nginx-1.20.2.tar.gz
cd nginx-1.20.2/;ls
重新编译安装#检测编译环境 加模块
./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 install
make
mv /apps/nginx/sbin/nginx /apps/nginx/sbin/nginx.bak
#将低版本的nginx主程序改名
cp /usr/local/src/nginx-1.20.2/objs/nginx /apps/nginx/sbin
#将新版本 拷入进去
/apps/nginx/sbin/nginx -t
#语法检查
kill -USR2 `cat /apps/nginx/logs/nginx.pid`ps auxf|grep nginx
#会生成新的master进程,需要结束旧的
cat /apps/nginx/los/nginx.pid #1.20.2版本的cat /apps/nginx/los/nginx.pid.oldbin #1.18版本的kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`
#优雅关闭 旧版本的master processpstree -p |grep nginxcurl -I http://localhost
#检查新版本是否实际生效,输出中应包含 Server: nginx/1.20.2。ps -ef | grep nginx | grep -v grep #验证旧 worker 已完全退出tail -n 20 /apps/nginx/logs/error.log
#检查错误日志,确保没有 bind() failed 或其他端口冲突错误。kill -QUIT `cat /apps/nginx/logs/nginx.pid.oldbin`
#如果确认新版本运行正常,可以安全关闭旧 master
6.3 回滚(退回旧版本)
回滚的本质是 重新激活旧 Master 的 Worker,并关闭新 Master。
所以必须满足以下条件才能回滚:
-
旧 Master 进程仍在运行
-
旧 Worker 已停止(通过
kill -WINCH
) -
未执行
kill -QUIT 旧PID
(否则旧 Master 会退出
#唤起旧版本的主进程
kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin`#结束新版本的master进程
kill -QUIT `cat /apps/nginx/logs/nginx.pid`curl -I 127.1
#通过 curl 发送一个 HEAD 请求到本地服务器并返回响应头信息
若旧 Master 已退出
解决方案:手动启动旧二进制文件
# 1. 关闭新版本
kill -TERM `cat /apps/nginx/logs/nginx.pid`# 2. 启动旧版本
cp /apps/nginx/sbin/nginx.bak /apps/nginx/sbin/nginx
/apps/nginx/sbin/nginx -t && /apps/nginx/sbin/nginx
若旧 Worker 未完全关闭
# 强制杀死残留 Worker
pkill -9 -f "nginx: worker process"
# 再执行标准回滚流程