真正理解 Nginx,从这一篇开始深入内核,掌握配置的艺术。
📘 第四章:核心原理·Nginx 为何如此之快
4.1 事件驱动模型:高并发的灵魂
Nginx 高并发的秘密,藏在它的 异步非阻塞事件驱动架构 中。
传统 Apache(多进程/多线程)模型:
text
每个请求 → 分配一个进程/线程 → 阻塞等待 I/O → 处理完成 → 释放
- 问题:10,000 并发 = 10,000 个进程/线程 → 系统资源瞬间爆炸 💥
Nginx(事件驱动)模型:
text
Master 进程(管理者)
├── 不处理请求,只负责管理 Worker
└── 创建多个 Worker 进程(通常 = CPU 核心数)
每个 Worker 进程(单线程,异步非阻塞)
├── 通过 epoll 同时监听数千个连接
├── 哪个连接有数据到达,就处理哪个
└── 没有数据时继续监听(绝不阻塞等待)
结果:1 个 Worker 可处理数万并发连接!
4.2 I/O 多路复用:epoll 的魔法
Nginx 在 Linux 下使用 epoll 实现高效的 I/O 多路复用。
c
// epoll 工作原理
epoll_fd = epoll_create(); // 创建 epoll 实例
for (conn in all_connections) {
epoll_ctl(epoll_fd, ADD, conn, EPOLLIN); // 注册所有连接的读事件
}
while (true) {
events = epoll_wait(epoll_fd); // 阻塞等待,直到有事件发生
for (ready_conn in events) { // 只遍历就绪的连接(O(1))
data = ready_conn.read();
handle(data);
}
}
I/O 模型对比(直观理解)
| I/O 模型 | 工作方式 | 性能 |
|---|---|---|
select |
轮询所有连接,最多 1024 个 | 差 |
poll |
类似 select,无数量限制 | 较差 |
epoll |
事件通知,只返回就绪连接 | 极好 |
kqueue |
FreeBSD/macOS 版 epoll | 极好 |
4.3 Master-Worker 进程模型
Nginx 的进程架构清晰而稳定:
text
Master 进程 (PID: 10086)
├─ 读取和验证配置
├─ 创建/管理 Worker
├─ 处理信号(reload等)
└─ 不处理客户端请求
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
Worker 1 Worker 2 Worker 3
├─ 处理请求 ├─ 处理请求 ├─ 处理请求
└─ 绑定 CPU 核心 0 └─ 绑定 CPU 核心 1 └─ 绑定 CPU 核心 2
│
┌────────────┴────────────┐
▼ ▼
共享内存(缓存、会话等) 磁盘/网络 I/O
Worker 进程数量配置 (nginx.conf):
nginx
worker_processes auto; # 自动 = CPU 核心数(推荐)
# worker_processes 4; # 或手动指定
# 绑定 Worker 到特定 CPU(减少上下文切换,提升性能)
worker_cpu_affinity 0001 0010 0100 1000; # 4 核示例
# 或 worker_cpu_affinity auto;
4.4 Worker 处理流程:一气呵成
text
客户端连接到达
│
▼
Worker 进程
│
├── ① accept 新连接
├── ② 读取 HTTP 请求
├── ③ 匹配配置规则(server_name / location)
├── ④ 根据配置处理
│ ├── 静态文件 → 直接返回
│ ├── 反向代理 → 转发给后端
│ └── FastCGI → 转发 PHP
├── ⑤ 返回响应
└── ⑥ 记录日志
│
│ 💡 关键:此期间可以同时处理其他连接!
│ 当一个连接等待 I/O 时,Worker 立即切换到另一个连接
4.5 为什么 Nginx 如此高效?------ 七大致胜法宝
| 因素 | 说明 |
|---|---|
| 🔧 Master-Worker 模型 | 稳定的进程管理,单个 Worker 崩溃不影响其他 |
| ⚡ epoll/kqueue | 操作系统级 I/O 通知,无轮询开销 |
| 🧵 异步非阻塞 | 一个线程可处理数万连接 |
| 📄 零拷贝(sendfile) | sendfile() 系统调用,内核态直接发送文件 |
| 🧠 内存池 | 预分配内存池,减少碎片和 malloc 开销 |
| 🧩 模块化设计 | 按需加载模块,核心极小 |
| 💾 异步 I/O 支持 | 进一步减少磁盘 I/O 阻塞 |
📂 第五章:核心目录与配置文件·庖丁解牛
5.1 整体目录结构(带注释)
text
/etc/nginx/ # 配置根目录
├── nginx.conf # 主配置文件
├── mime.types # MIME 类型映射(如 .css → text/css)
├── conf.d/ # 自定义配置目录(推荐拆分配置)
│ ├── default.conf # 默认站点
│ └── example.com.conf # 自定义站点
├── sites-available/ # Ubuntu 风格:所有可用站点
├── sites-enabled/ # Ubuntu 风格:已启用站点(软链接)
├── fastcgi.conf # FastCGI 参数(PHP 动态处理)
├── uwsgi_params # uWSGI 参数(Python 应用)
└── ...
/usr/share/nginx/html/ # 默认站点根目录(存放静态文件)
/var/log/nginx/ # 日志目录
├── access.log # 访问日志(每次请求)
└── error.log # 错误日志(调试用)
/usr/sbin/nginx # 可执行文件
/run/nginx.pid # PID 文件(记录主进程号)
5.2 主配置文件完整结构(简化+注释)
nginx
# ====== ① 全局块 ======
user nginx; # Worker 进程运行的用户(安全)
worker_processes auto; # Worker 数量,auto = CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志级别
pid /run/nginx.pid; # PID 文件路径
# ====== ② events 块 ======
events {
worker_connections 1024; # 每个 Worker 最大并发连接数
use epoll; # Linux 下使用 epoll 模型
multi_accept on; # 一次 accept 尽可能多接收连接
accept_mutex off; # 高并发下关闭互斥锁,提升性能
}
# ====== ③ http 块 ======
http {
# --- 基础配置 ---
include /etc/nginx/mime.types; # 引入 MIME 类型表
default_type application/octet-stream; # 默认类型(二进制流)
# --- 日志格式定义 ---
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# --- 性能优化 ---
sendfile on; # 启用零拷贝(直接内核态发送文件)
tcp_nopush on; # 与 sendfile 配合,一次发送完整包
tcp_nodelay on; # 禁用 Nagle 算法,实时发送小数据
keepalive_timeout 65; # 长连接保持时间(秒)
server_tokens off; # 隐藏 Nginx 版本号(安全)
# --- Gzip 压缩(减少带宽)---
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# --- 请求体限制(防超大数据包)---
client_max_body_size 10m; # 最大上传大小
client_body_timeout 12; # 读取请求体超时
client_header_timeout 12; # 读取请求头超时
# --- 引入子配置(模块化)---
include /etc/nginx/conf.d/*.conf;
}
5.3 配置块层级关系(一目了然)
text
main (全局块)
│
├── events 块 ← 连接处理(epoll、连接数等)
│
├── http 块 ← HTTP 协议相关(gzip、日志、上游等)
│ │
│ ├── server 块 ← 虚拟主机(一个域名一个 server)
│ │ ├── location / ← 处理根路径
│ │ ├── location /api/ ← 处理 API 路径
│ │ └── location ~ \.php$ ← 正则匹配 PHP 文件
│ │
│ └── upstream 块 ← 定义一组后端服务器(用于负载均衡)
│
├── stream 块 ← 四层代理(TCP/UDP 转发)
│
└── mail 块 ← 邮件代理(很少用)
继承规则:
- 子块自动继承父块的所有配置
- 子块可以覆盖父块的相同指令
location→server→http→ 全局
5.4 子配置文件拆分规范(生产推荐)
text
/etc/nginx/conf.d/
├── upstream.conf # 后端服务器组(如 backend_servers)
├── gzip.conf # Gzip 压缩相关
├── ssl.conf # SSL 通用配置(TLS 版本、证书路径等)
├── proxy.conf # 反向代理通用参数(如 proxy_pass 头信息)
├── cache.conf # 缓存路径、过期策略
├── example.com.conf # 具体站点配置(含 server 块)
└── api.example.com.conf # 另一个站点
在 nginx.conf 中统一引入:
nginx
http {
include /etc/nginx/conf.d/upstream.conf;
include /etc/nginx/conf.d/gzip.conf;
include /etc/nginx/conf.d/ssl.conf;
include /etc/nginx/conf.d/proxy.conf;
include /etc/nginx/conf.d/*.site.conf; # 通配符引入站点
}
⚙️ 第六章:常用核心命令·运维必备
6.1 基本运维命令(带注释)
bash
# ----- 启停 -----
nginx # 启动(需以 root 或 sudo 执行)
nginx -s stop # 快速停止(强制终止)
nginx -s quit # 优雅停止(处理完当前请求再退出)
nginx -s reload # 最常用:重载配置(不中断服务)
nginx -s reopen # 重新打开日志文件(日志切割后使用)
# ----- 配置检查 -----
nginx -t # 改完配置必执行:测试语法
nginx -T # 测试并打印完整配置(含所有 include)
nginx -v # 查看版本号
nginx -V # 查看版本 + 编译参数(确认模块支持)
6.2 状态查看命令(精简版)
bash
# 查看进程
ps aux | grep nginx
# 预期输出:master process (root) + worker process (www)
# 查看监听端口
ss -tlnp | grep nginx # 应显示 80/443 等端口 LISTEN
# 查看实时连接数
netstat -an | grep :80 | wc -l
6.3 日志分析命令(常用场景)
bash
# 实时跟踪错误日志
tail -f /var/log/nginx/error.log
# 统计访问来源 IP 的 TOP 10
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 统计 HTTP 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
6.4 日志切割(logrotate 自动化)
bash
# 创建 logrotate 配置文件
cat > /etc/logrotate.d/nginx << 'EOF'
/var/log/nginx/*.log {
daily # 每天切割
rotate 30 # 保留 30 份
compress # 压缩旧日志
delaycompress # 延迟一天压缩(保留昨天的原始)
notifempty # 空文件不切割
create 640 nginx adm # 新文件权限
sharedscripts
postrotate
# 通知 Nginx 重新打开日志文件(关键!)
[ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
EOF
# 手动测试
logrotate -d /etc/logrotate.d/nginx
# 手动执行一次
logrotate -f /etc/logrotate.d/nginx
6.5 配置文件管理脚本(简化核心)
bash
#!/bin/bash
# nginx-manage.sh --- 日常四件事
case "$1" in
test)
nginx -t # 测试配置
;;
reload)
nginx -t && nginx -s reload # 测试通过后重载
;;
backup)
dir="/data/bck/nginx/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$dir"
cp -r /etc/nginx/nginx.conf "$dir/"
cp -r /etc/nginx/conf.d "$dir/"
echo "备份完成:$dir"
;;
status)
ps aux | grep nginx | grep -v grep
ss -tlnp | grep nginx
;;
*)
echo "用法: $0 {test|reload|backup|status}"
;;
esac
6.6 性能监控(简单实用)
bash
# 查看连接状态统计
netstat -an | awk '/^tcp/ {++state[$NF]} END {for(i in state) print i, state[i]}'
# 实时查看每秒请求量(需安装 pv)
tail -f /var/log/nginx/access.log | pv -l -i 1 > /dev/null
# 启用 stub_status 模块后,可执行(配置方法见后续章节)
curl http://localhost/nginx_status
# 输出:Active connections, accepts, handled, requests 等