Nginx 配置详解
🔐 适用场景:Web服务器配置、反向代理、负载均衡、静态资源服务
📑 目录
1. Nginx 基础架构
1.1 什么是 Nginx
Nginx(发音为"engine-x")是一款开源的高性能HTTP服务器和反向代理服务器,由俄罗斯程序员Igor Sysoev于2004年首次发布。它以其高并发、低内存消耗和稳定性著称,目前已被全球约三分之一的网站采用。
┌─────────────────────────────────────────────────────────┐
│ 🟣 Nginx │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Master │ │ Worker │ │ Worker │ │
│ │ Process │──│ Process │ │ Process │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ┌─────┴────────────────┴────────────────┴─────┐ │
│ │ 🔵 Connection Pool │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
1.2 核心概念解释
| 概念 | 解释 |
|---|---|
| Master Process(主进程) | Nginx的启动进程,负责读取配置文件、管理Worker进程、接收信号、重载配置等管理工作。它不处理实际的用户请求,而是监控和管理Worker进程的状态。 |
| Worker Process(工作进程) | 实际处理用户请求的进程。Master进程会fork出多个Worker进程,每个Worker独立处理请求。Worker进程之间通过共享内存进行通信。 |
| Connection Pool(连接池) | Nginx使用连接池来管理客户端连接,避免频繁创建和销毁连接的开销。每个Worker进程有自己的连接池。 |
| Event-Driven(事件驱动) | Nginx采用事件驱动架构,使用epoll(Linux)、kqueue(FreeBSD/macOS)、select/poll等高效的事件通知机制,能够同时处理大量并发连接。 |
| Non-blocking I/O(非阻塞I/O) | Nginx使用非阻塞I/O操作,当等待I/O操作完成时,进程可以继续处理其他请求,从而最大化资源利用率。 |
1.3 架构特点详解
| 🎯 特性 | 📄 说明 |
|---|---|
| 🐧 多进程 | Master-Worker模式:Master进程负责管理(读取配置、发出信号),Worker进程负责处理请求。Worker数量通常设置为CPU核心数,可通过worker_processes配置。 |
| 🔄 事件驱动 | Nginx使用epoll(Linux 2.6+)、kqueue(BSD/macOS)、select/poll等高效事件模型,能够同时处理数十万个并发连接。 |
| 📦 模块化 | Nginx采用模块化设计,核心模块提供基础功能,第三方模块(如SSL、压缩、重写等)可按需加载。 |
| ⚡ 高性能 | 得益于事件驱动和非阻塞I/O,Nginx能以少量进程处理大量并发请求,内存消耗极低。 |
| 🛡️ 热部署 | 可以在不中断服务的情况下重载配置、更换日志文件、更新Nginx本身(通过USR2信号)。 |
2. 安装与启动
2.1 什么是安装方式
| 安装方式 | 解释 | 适用场景 |
|---|---|---|
| 包管理器安装(apt/yum/brew) | 通过操作系统自带的包管理器安装,是最简单的方式 | 快速部署、不需要特殊模块 |
| 源码编译安装 | 从官网下载源码,使用./configure配置后编译安装 |
需要定制化模块、生产环境追求最新版本 |
| Docker | 使用官方Docker镜像 | 开发环境、容器化部署 |
apt/yum/brew 的区别:
- apt:Debian/Ubuntu 系发行版的包管理器
- yum:RHEL/CentOS 旧版本的包管理器
- dnf:RHEL/CentOS 新版本的包管理器(yum的升级版)
- brew:macOS 的包管理器
2.2 安装方式
# 🖥️ Ubuntu/Debian(使用apt包管理器)
sudo apt update && sudo apt install nginx
# 🖥️ CentOS/RHEL(使用dnf/yum包管理器)
sudo yum install nginx # 旧版本
sudo dnf install nginx # 新版本
# 🖥️ macOS(使用Homebrew包管理器)
brew install nginx
# 🖥️ 源码编译安装
# 1. 下载源码:https://nginx.org/en/download.html
# 2. 解压后进入目录
# 3. 配置编译选项
./configure --prefix=/usr/local/nginx --with-http_ssl_module
# 4. 编译并安装
make && make install
2.3 启动与管理命令详解
| 命令 | 解释 | 信号类型 |
|---|---|---|
systemctl start nginx |
使用systemd服务管理器启动Nginx | systemd是现代Linux的初始化系统 |
nginx |
直接启动Nginx(不通过systemd) | 适用于没有systemd的环境 |
systemctl stop nginx |
强制停止Nginx服务 | 发送TERM信号 |
systemctl stop nginx |
发送QUIT信号,优雅停止(等待现有请求处理完) | QUIT信号的优雅停止 |
nginx -s reload |
发送HUP信号,重新加载配置文件 | 不中断现有连接 |
nginx -t |
测试配置文件语法是否正确 | 不实际重载 |
nginx -s stop |
发送TERM信号,立即停止 | 强制停止 |
nginx -s quit |
发送QUIT信号,优雅停止 | 等待请求处理完毕后停止 |
nginx -v |
显示Nginx版本号 | 仅查看版本 |
nginx -V |
显示Nginx版本、编译参数和配置参数 | 调试时使用 |
2.4 启动与管理命令
# 🔧 启动 Nginx
sudo systemctl start nginx # systemd
sudo nginx # 直接启动
# 🔧 停止 Nginx
sudo systemctl stop nginx
# 🔧 重载配置(不断开连接)
sudo nginx -s reload
# 🔧 检查配置语法
sudo nginx -t
# 🔧 查看版本
nginx -v
┌─────────────────────────────────────────────────────┐
│ 🔧 Nginx 进程管理流程 │
│ │
│ ┌──────────┐ reload ┌──────────┐ │
│ │ Master │──────────────│ Master │ │
│ │ (old) │ │ (new) │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ │ 向旧workers发QUIT信号 │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Worker │ → │ Worker │ │
│ │ (old) │ 停止处理 │ (new) │ │
│ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────┘
3. 核心配置结构
3.1 配置文件位置详解
| 🗂️📁 路径 | 📄 说明 | 备注 |
|---|---|---|
/etc/nginx/nginx.conf |
主配置文件,Nginx启动时默认读取 | 所有配置文件的入口 |
/etc/nginx/conf.d/ |
自定义配置目录,用于存放额外的server块配置 | 通常放server配置 |
/etc/nginx/sites-enabled/ |
站点配置目录(Debian/Ubuntu特有) | 通过符号链接启用站点 |
/usr/local/nginx/conf/ |
源码编译安装的默认路径 | 编译安装时指定的prefix路径 |
为什么要有多个配置目录?
- 模块化:不同站点/功能的配置分开管理
- 便于维护:修改一个站点配置不影响其他站点
- 避免冲突:多人协作时不易产生冲突
3.2 配置块层级概念
Nginx配置由多个配置块(Block)组成,形成层级结构:
| 配置块 | 名称 | 作用 | 包含的子块 |
|---|---|---|---|
| main(全局块) | 最外层配置 | 设置Nginx运行的整体参数 | events块、http块 |
| events块 | 事件块 | 配置连接处理方式 | 无 |
| http块 | HTTP块 | HTTP服务器相关配置 | server块、upstream块 |
| server块 | 虚拟主机块 | 定义单个站点的配置 | location块 |
| location块 | URL路由块 | 根据URL路径处理请求 | 无 |
| upstream块 | 上游服务器块 | 定义后端服务器组(负载均衡) | 无 |
3.3 配置指令层级图
┌─────────────────────────────────────────────────────┐
│ 🟣 main context(全局块) │
│ ┌─────────────────────────────────────────────────┐│
│ │ user, worker_processes, error_log, pid ││
│ └─────────────────────────────────────────────────┘│
│ ▼ │
│ ┌─────────────────────────────────────────────────┐│
│ │ 🔵 events 块 ││
│ │ ┌─────────────────────────────────────────────┐││
│ │ │ worker_connections, use, multi_accept │││
│ │ └─────────────────────────────────────────────┘││
│ └─────────────────────────────────────────────────┘│
│ ▼ │
│ ┌─────────────────────────────────────────────────┐│
│ │ 🟢 http 块 ││
│ │ ┌─────────────────────────────────────────────┐││
│ │ │ include, log_format, access_log, gzip │││
│ │ └─────────────────────────────────────────────┘││
│ │ ▼ ││
│ │ ┌─────────────────────────────────────────────┐││
│ │ │ 🟢 server 块(虚拟主机) │││
│ │ │ ┌───────────────────────────────────────┐ │││
│ │ │ │ listen, server_name, ssl_certificate│ │││
│ │ │ └───────────────────────────────────────┘ │││
│ │ │ ▼ │││
│ │ │ ┌───────────────────────────────────────┐ │││
│ │ │ │ 🟡 location 块(URL路由) │ │││
│ │ │ │ root, index, proxy_pass, try_files │ │││
│ │ │ └───────────────────────────────────────┘ │││
│ │ └─────────────────────────────────────────────┘││
│ └─────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────┘
3.4 配置文件检查详解
nginx -t 是部署前最重要的命令,用于验证配置文件的语法和逻辑正确性。
# 🔧 测试配置语法(最常用)
sudo nginx -t
# 输出:nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# 输出:nginx: configuration file /etc/nginx/nginx.conf test is successful
# 🔧 查看完整配置(含引入文件展开)- 用于调试include指令
sudo nginx -T
# 🔧 指定配置文件路径测试 - 用于测试非默认位置的配置文件
sudo nginx -t -c /path/to/nginx.conf
| 命令 | 解释 | 使用场景 |
|---|---|---|
nginx -t |
测试配置文件语法和有效性 | 重载配置前必用 |
nginx -T |
测试并打印完整配置(包括include的文件内容) | 调试配置include问题 |
nginx -t -c path |
测试指定路径的配置文件 | 测试备选配置文件 |
4. HTTP 服务器配置
4.1 基础虚拟主机详解
虚拟主机(Virtual Host) 是Nginx通过server块来区分不同网站(或域名的机制。Nginx通过请求的Host来识别应该哪个server块处理请求。
| 概念 | 解释 |
|---|---|
| listen | 监听端口,指定Nginx在这个端口上接受请求。80是HTTP标准端口,443是HTTPS标准端口 |
| server_name | 服务器域名,用于匹配请求头中的Host字段。可以是精确域名、通配符或正则表达式 |
| root | 文档根目录,定义网站文件存放的物理路径。请求的URI会追加到此目录下查找文件 |
| index | 默认首页文件,当请求目录而非文件时,Nginx会按顺序查找这些文件 |
| access_log | 访问日志路径,记录所有入站请求的信息 |
| error_log | 错误日志路径,记录服务器错误和警告 |
| try_files | 尝试查找文件的规则,按顺序检查文件/目录是否存在,不存在则回退到指定URI或返回错误码 |
| expires | 设置缓存过期时间,30d表示30天 |
| add_header | 向响应添加自定义HTTP头部 |
server {
listen 80; # 监听80端口(HTTP标准端口)
server_name example.com; # 域名配置,支持精确匹配、通配符、正则
# 文档根目录 - 网站文件存放的物理路径
root /var/www/example.com/html;
# 默认首页 - 当请求目录时按顺序查找
index index.html index.htm;
# 访问日志 - 记录所有请求
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# location 路由 - 根据URL路径处理请求
location / {
# try_files:依次尝试 $uri(文件)、$uri/(目录)、=404(返回404)
try_files $uri $uri/ =404;
}
# 静态资源缓存 - /static/ 路径下的文件缓存30天
location /static/ {
expires 30d; # 缓存30天
add_header Cache-Control "public, immutable"; # 公开缓存、不可变性
}
# 错误页面 - 自定义错误页面
error_page 404 /404.html; # 404时显示/404.html
error_page 500 502 503 504 /50x.html; # 5xx服务器错误时显示/50x.html
}
4.2 server_name 多种配置详解
server_name指令用于匹配请求头中的Host字段,支持多种配置方式:
| 配置方式 | 示例 | 匹配规则 |
|---|---|---|
| 精确匹配 | server_name example.com |
仅匹配example.com |
| 多个域名 | server_name example.com www.example.com |
匹配多个指定域名 |
| 通配符(首) | server_name *.example.com |
匹配任何子域名(如sub.example.com) |
| 通配符(尾) | server_name example.* |
匹配example开头的任何后缀(如example.com、example.org) |
| 正则表达式 | server_name ~^www\d+\.example\.com$ |
使用正则匹配(以~开头) |
| 默认服务器 | server_name _ 或 server_name "" |
处理所有未匹配的请求 |
server {
# 精确匹配
server_name example.com;
# 多个域名(按顺序匹配)
server_name example.com www.example.com;
# 通配符(只能在首尾)—— 匹配 sub.example.com
server_name *.example.com;
# 另一个通配符示例 —— 匹配 example.com example.org example.net
server_name example.*;
# 正则表达式(以 ~ 开头)—— 匹配 www1.example.com, www2.example.com
server_name ~^www\d+\.example\.com$;
# 默认服务器 —— 处理未匹配的所有请求(兜底)
server_name _; # 或使用空字符串 ""
}
4.3 location 匹配规则详解
location块用于根据请求的URI路径来定义如何处理请求。Nginx支持多种匹配类型:
| 语法 | 名称 | 说明 |
|---|---|---|
location /uri |
前缀匹配 | 匹配以/uri开头的路径(最常用) |
location / |
根匹配 | 匹配所有路径 |
location = /exact |
精确匹配 | 精确匹配URI,优先级最高 |
location ^~ /prefix |
前缀匹配(禁用正则) | 匹配前缀路径,并禁用该location后的正则匹配 |
location ~ /regex |
正则匹配(区分大小写) | 使用正则表达式匹配(区分大小写) |
location ~* /regex |
正则匹配(不区分大小写) | 使用正则表达式匹配(不区分大小写) |
4.4 location 优先级详解
Nginx按以下优先级顺序匹配location(从高到低):
┌─────────────────────────────────────────────────────────┐
│ 🟡 Location 匹配优先级 │
│ │
│ 🟣 1. = (精确匹配) │
│ └─ location = /exact │
│ 最高优先级,完全相等才匹配 │
│ │
│ 🔵 2. ^~ (前缀匹配,禁用正则) │
│ └─ location ^~ /prefix │
│ 匹配前缀路径,匹配后不再检查正则 │
│ │
│ 🟢 3. ~ 或 ~* (正则匹配,按顺序匹配) │
│ └─ location ~ \.(jpg|png|gif)$ │
│ 按配置文件中的顺序匹配,第一个匹配的生效 │
│ │
│ 🟡 4. 普通前缀匹配(最长前缀匹配) │
│ └─ location /path │
│ └─ location /path/deeper │
│ 匹配最长的前缀 │
│ │
└─────────────────────────────────────────────────────────┘
优先级总结:
=精确匹配 → 最高优先级^~前缀匹配(禁用正则)→ 次高优先级~或~*正则匹配 → 按书写顺序,第一个匹配的成功- 普通前缀匹配 → 匹配最长前缀
4.5 完整配置示例详解
这是一个典型的Web应用配置,包含了静态资源、PHP处理、安全控制等常用配置:
server {
listen 80; # 监听端口
server_name www.example.com example.com; # 多个域名
root /var/www/example.com; # 文档根目录
index index.html; # 默认首页
# 根路径 —— try_files 依次尝试文件、目录,最后回退到 /index.html
location / {
try_files $uri $uri/ /index.html;
}
# PHP 处理(使用 php-fpm)—— 正则匹配 .php 结尾的请求
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock; # PHP-FPM Unix socket 路径
fastcgi_index index.php; # 默认首页
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 完整脚本路径
include fastcgi_params; # 引入 fastcgi 参数
}
# 静态资源(带缓存)—— 不区分大小写正则匹配静态文件
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
expires 1y; # 缓存1年
access_log off; # 关闭访问日志(减少IO)
add_header Cache-Control "public, immutable"; # 公开缓存、不可变性
}
# 禁止访问隐藏文件 —— 正则匹配以 . 开头的路径
location ~ /\. {
deny all; # 拒绝所有访问
access_log off; # 关闭访问日志
log_not_found off; # 关闭"文件未找到"日志
}
# 禁止访问敏感路径 —— 匹配 .git、.env 等敏感目录
location ~* /\.(git|env|htaccess|htpasswd) {
deny all;
}
# 错误页面 —— 自定义错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
5. 反向代理配置
5.1 反向代理概念详解
反向代理(Reverse Proxy) 是指Nginx作为代理服务器,代替客户端向后端服务器发起请求,并将后端服务器的响应转发回客户端。与正向代理(代理客户端)相反,反向代理对客户端是透明的。
| 概念 | 正向代理 | 反向代理 |
|---|---|---|
| 代理对象 | 客户端(浏览器) | 服务器(后端应用) |
| 用途 | FQ、缓存、访问控制 | 负载均衡、安全防护、缓存加速 |
| 客户端知道吗 | 知道(需配置代理) | 不知道(像访问真实服务器) |
| 代表软件 | Squid | Nginx、HAProxy |
┌─────────────────────────────────────────────────────────┐
│ 🔄 Nginx 反向代理请求流程 │
│ │
│ Client(不知道后端存在) │
│ │ │
│ │ ① 请求 www.example.com │
│ ▼ │
│ ┌────────┐ │
│ │ 🟣 │ Nginx (代理服务器) │
│ │ Nginx │ 客户端以为这是真实服务器 │
│ └────┬───┘ │
│ │ ② 转发请求到后端服务器(对客户端透明) │
│ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 🔵 │ │ 🔵 │ │ 🔵 │ │
│ │Backend │ │Backend │ │Backend │ │
│ │ :3000 │ │ :3001 │ │ :3002 │ │
│ └────────┘ └────────┘ └────────┘ │
│ │ ③ 返回响应 │
│ ▼ │
│ Client ←── ④ 转发响应(看起来像Nginx返回的) │
│ │
└─────────────────────────────────────────────────────────┘
5.2 代理到后端服务器详解
proxy_pass是反向代理的核心指令,用于指定后端服务器的地址。
| 指令 | 说明 |
|---|---|
| proxy_pass | 反向代理目标地址,可以是http://、https://或unix:路径 |
| proxy_set_header | 设置转发给后端的请求头(非常重要!) |
| proxy_connect_timeout | 与后端建立连接的超时时间 |
| proxy_send_timeout | 向后端发送请求的超时时间 |
| proxy_read_timeout | 等待后端响应的超时时间 |
| proxy_buffering | 是否启用缓冲区(开启可提高性能) |
| proxy_buffer_size | 响应头缓冲区大小 |
| proxy_buffers | 响应体缓冲区数量和大小 |
重要Headers说明:
| Header | 解释 | 为什么要传 |
|---|---|---|
Host $host |
请求的域名 | 后端应用需要知道请求哪个虚拟主机 |
X-Real-IP $remote_addr |
客户端真实IP | 后端需要记录真实客户端IP |
X-Forwarded-For |
代理链IP列表 | 追踪请求经过的代理链 |
X-Forwarded-Proto |
原始协议 | 后端知道是http还是https |
server {
listen 80;
server_name www.example.com;
# 代理到后端应用
location / {
proxy_pass http://127.0.0.1:3000; # 后端服务器地址
# 传递原始请求头(重要!否则后端无法获取真实信息)
proxy_set_header Host $host; # 原始域名
proxy_set_header X-Real-IP $remote_addr; # 客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 代理链
proxy_set_header X-Forwarded-Proto $scheme; # 原始协议
# 超时配置(单位:s=秒,ms=毫秒)
proxy_connect_timeout 60s; # 连接后端超时
proxy_send_timeout 60s; # 发送数据超时
proxy_read_timeout 60s; # 读取响应超时
# 缓冲配置(提升性能)
proxy_buffering on; # 启用缓冲
proxy_buffer_size 4k; # 响应头缓冲大小
proxy_buffers 8 4k; # 响应体缓冲(8个,每个4k)
}
# 代理到特定路径 —— 末尾 / 会替换 location 路径部分
location /api/ {
# 请求 /api/users 会被代理到 http://127.0.0.1:8080/users
# 因为末尾有 /,所以 /api/ 被替换为 /
proxy_pass http://127.0.0.1:8080/;
}
}
5.3 WebSocket 代理详解
WebSocket 是一种双向通信协议,与传统HTTP轮询不同,它允许服务器主动推送数据。Nginx从1.3版本开始支持WebSocket代理。
WebSocket与HTTP的区别:
- HTTP:请求-响应模式,客户端先发请求,服务器才能响应
- WebSocket:建立连接后,客户端和服务器都可以随时发送数据
- WebSocket通过HTTP的Upgrade机制建立
location /ws/ {
proxy_pass http://127.0.0.1:8000/ws/; # WebSocket后端地址
# WebSocket 必须配置这三个指令
proxy_http_version 1.1; # 必须使用HTTP/1.1
proxy_set_header Upgrade $http_upgrade; # 升级协议
proxy_set_header Connection "upgrade"; # 升级连接
# 超时(WebSocket是长连接,需要更长超时)
proxy_read_timeout 86400s; # 24小时
proxy_send_timeout 86400s;
}
5.4 uWSGI 代理(Python应用)
uWSGI 是Python Web应用的常见部署方式,通常配合Nginx作为前端代理。
location / {
include /etc/nginx/uwsgi_params; # 引入uWSGI参数定义
uwsgi_pass 127.0.0.1:5000; # uWSGI监听地址
}
6. 负载均衡
6.1 负载均衡概念详解
负载均衡(Load Balancing) 是一种将传入的网络流量分配到多个后端服务器的技术,目的是优化资源使用、最大化吞吐量、减少延迟、避免单点故障。
| 概念 | 解释 |
|---|---|
| upstream | Nginx中定义后端服务器组的配置块,所有负载均衡策略都在此定义 |
| 后端服务器(Backend) | 实际处理请求的应用服务器 |
| 负载均衡算法 | 决定请求分发到哪个后端的策略 |
┌─────────────────────────────────────────────────────────┐
│ 🔄 Nginx 负载均衡架构 │
│ │
│ Client │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ 🟣 │ │
│ │ Nginx │ │
│ │ (LB) │ │
│ └─────┬──────┘ │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 🔵 │ │ 🔵 │ │ 🔵 │ │
│ │Backend1 │ │Backend2 │ │Backend3 │ │
│ │ :8080 │ │ :8081 │ │ :8082 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
6.2 轮询(Round Robin)详解
轮询是Nginx默认的负载均衡策略,按顺序将请求分配到每台服务器,每个服务器获得大致相等的请求数量。
- 优点:简单、均匀分布、无需额外配置
- 缺点:不考虑服务器性能差异、不考虑当前负载
http {
# 定义上游服务器组
upstream backend {
server 127.0.0.1:8080; # 第1台服务器
server 127.0.0.1:8081; # 第2台服务器
server 127.0.0.1:8082; # 第3台服务器
server 127.0.0.1:8083; # 第4台服务器
# 请求会按 1→2→3→4→1→2... 循环分配
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend; # 使用backend服务器组
}
}
}
6.3 加权轮询详解
加权轮询允许为每台服务器设置权重值,性能更好的服务器设置更高权重,获得更多请求。
- weight参数:权重值,默认1,数值越大获得的请求比例越高
- 计算方式:若服务器A weight=5,服务器B weight=1,则A获得5/6的请求,B获得1/6
upstream backend {
server 127.0.0.1:8080 weight=5; # 权重5,每6个请求中获得5个
server 127.0.0.1:8081 weight=3; # 权重3,每6个请求中获得3个
server 127.0.0.1:8082 weight=2; # 权重2,每6个请求中获得2个
server 127.0.0.1:8083; # 权重1(默认),每6个请求中获得1个
}
6.4 最少连接(Least Connections)详解
最少连接策略将请求分配给当前连接数最少的服务器,适合长时间连接的场景(如WebSocket、数据库连接池)。
upstream backend {
least_conn; # 启用最少连接策略
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
6.5 IP Hash详解
IP Hash使用客户端IP的哈希值来决定分配到哪台服务器,同一IP的请求始终发送到同一台服务器。
- 优点:会话保持,用户状态可以保存在后端服务器
- 缺点:服务器数量变化时,大量用户可能被重新分配
upstream backend {
ip_hash; # 启用IP Hash策略
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
6.6 URL Hash(权重Hash)详解
URL Hash使用请求URL的哈希值来分配请求,相同URL的请求会发送到同一台服务器。consistent参数启用一致性哈希,服务器变化时影响范围更小。
upstream backend {
hash $request_uri consistent; # 基于URI的Hash,consistent减少重分配
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
6.7 健康检查详解
Nginx提供被动健康检查功能,当后端服务器连续失败达到一定次数后,会被标记为不可用。
| 参数 | 说明 | 默认值 |
|---|---|---|
| max_fails | 失败次数达到此值则标记为不可用 | 1 |
| fail_timeout | 不可用持续时间,之后重新尝试 | 10秒 |
| backup | 标记为备份服务器,仅在主服务器全挂时启用 | - |
| down | 永久标记为不可用 | - |
upstream backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; # 30秒内失败3次,标记为不可用,30秒后重试
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8082 backup; # 备份服务器,只有前两个都不可用时才会使用
server 127.0.0.1:8083 down; # 永久不可用
}
7. HTTPS 配置
7.1 HTTPS与SSL概念详解
HTTPS(Hypertext Transfer Protocol Secure) 是HTTP的安全版本,通过SSL/TLS协议加密传输数据。SSL(Secure Sockets Layer) 是早期的加密协议,已被TLS(Transport Layer Security) 取代,但人们仍习惯用SSL称呼。
| 概念 | 解释 |
|---|---|
| SSL证书 | 证明服务器身份的数字证书,由可信CA颁发 |
| 证书链(fullchain.pem) | 包含服务器证书和中间CA证书 |
| 私钥(privkey.pem) | 用于解密的对称密钥,必须保密 |
| TLS协议 | SSL的升级版,目前主流版本是TLSv1.2和TLSv1.3 |
| 加密套件(Cipher Suite) | 加密算法的组合,决定加密强度 |
| OCSP Stapling | 服务器直接提供证书状态检查结果,加速验证 |
| 会话缓存(Session Cache) | 复用已建立的SSL会话,避免重复握手 |
server {
listen 443 ssl; # 监听443端口,启用SSL
server_name example.com www.example.com;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/fullchain.pem; # 证书链文件(包含服务器证书+中间CA)
ssl_certificate_key /etc/nginx/ssl/privkey.pem; # 私钥文件(必须保密)
# TLS协议版本(推荐只启用TLSv1.2和TLSv1.3,禁用旧版SSL)
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件配置(使用现代加密算法)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on; # 服务器端加密套件优先(客户端次之)
# SSL会话配置(提升性能)
ssl_session_cache shared:SSL:10m; # 共享会话缓存,大小10MB
ssl_session_timeout 1d; # 会话缓存有效期1天
ssl_session_tickets off; # 禁用会话票证(更安全)
# OCSP Stapling(在线证书状态协议 stapling)
ssl_stapling on; # 启用OCSP stapling
ssl_stapling_verify on; # 验证OCSP响应
resolver 8.8.8.8 8.8.4.4 valid=300s; # DNS解析器(用于查询OCSP服务器)
resolver_timeout 5s; # DNS查询超时
}
7.2 HTTP 跳转 HTTPS 详解
将所有HTTP请求强制跳转到HTTPS,提高安全性。
# HTTP服务器 —— 监听80端口,处理所有HTTP请求
server {
listen 80; # HTTP标准端口
server_name example.com www.example.com;
return 301 https://$host$request_uri; # 301永久重定向到HTTPS
}
# HTTPS服务器 —— 监听443端口
server {
listen 443 ssl; # SSL启用
server_name example.com www.example.com;
# ... SSL配置 ...
}
7.3 Let's Encrypt 免费证书详解
Let's Encrypt 是一个非营利CA,提供免费的SSL/TLS证书。certbot是其官方客户端,可自动申请和续期证书。
# 安装 certbot 和 Nginx 插件
sudo apt install certbot python3-certbot-nginx
# 申请证书并自动配置 Nginx(推荐)
sudo certbot --nginx -d example.com -d www.example.com
# 单独申请证书(不修改nginx配置)
sudo certbot certonly --nginx -d example.com -d www.example.com
# 测试自动续期(实际续期由cron/systemd timer执行)
sudo certbot renew --dry-run
7.4 双向认证(mTLS)详解
双向认证(mTLS,Mutual TLS) 除了服务器提供证书验证身份外,服务器也要求客户端提供证书验证身份。适用于企业内部系统、API安全等场景。
server {
listen 443 ssl;
server_name example.com;
# 客户端证书验证配置
ssl_client_certificate /etc/nginx/ssl/ca.crt; # CA证书(用于验证客户端证书)
ssl_verify_client on; # 要求客户端提供证书(可选值:on/optional/off)
location / {
# 检查客户端证书验证状态
if ($ssl_client_verify != SUCCESS) {
return 403; # 证书验证失败返回403
}
}
}
| ssl_verify_client 值 | 说明 |
|---|---|
| off | 不要求客户端证书(默认) |
| on | 要求客户端证书,验证失败拒绝连接 |
| optional | 要求客户端证书,但验证失败仍允许继续(可通过变量判断) |
8. 高级特性
8.1 Rewrite 规则详解
Rewrite 用于修改请求的URI,常用于URL重写、重定向、旧链接跳转等场景。
| 概念 | 解释 |
|---|---|
| rewrite指令 | 执行URL重写,可使用正则表达式捕获分组 |
| permanent | 301永久重定向,浏览器会缓存 |
| redirect | 302临时重定向,浏览器不缓存 |
| last | 重写后重新搜索location(内部重写) |
| break | 停止rewrite匹配,使用当前结果 |
# 永久重定向(301)—— 告诉浏览器和搜索引擎这是永久变更
rewrite ^/old-page$ /new-page permanent;
# 临时重定向(302)—— 用于临时跳转
rewrite ^/old-page$ /new-page redirect;
# 正则重写(捕获分组)—— 将 /blog/2024/01/article 重写为 /article-article-2024-01
rewrite ^/blog/(\d+)/(\d+)/(.+)$ /article/$3-$1-$2 permanent;
# 内部重写(不改变URL)—— URL不变,但内部转发到目标文件
rewrite ^/search/(.+)$ /search.php?q=$1 last;
# 标志位说明
# last - 重写后重新匹配location(用于内部跳转)
# break - 停止rewrite匹配(用于内部重写)
# redirect - 临时重定向(302)
# permanent - 永久重定向(301)
8.2 Nginx变量详解
Nginx提供了丰富的内置变量,可以在配置中引用这些值。
| 变量 | 说明 | 示例值 |
|---|---|---|
| $host | 请求行中的域名或server_name匹配的值 | example.com |
| $uri | 请求的URI(不含查询参数,不包含开头/) | /index.html |
| $request_uri | 完整原始URI(含查询参数) | /index.html?foo=bar |
| $args | 查询字符串(?后的部分) | foo=bar&baz=qux |
| $remote_addr | 客户端IP地址 | 192.168.1.100 |
| $http_header | 任意请求头(-换成_,大写变小写) | $http_user_agent |
| $scheme | 协议方案 | http 或 https |
| $document_root | 当前请求的root指令值 | /var/www/html |
| $server_name | 匹配的server名称 | example.com |
| $request_method | 请求方法 | GET、POST |
| $request_filename | 当前请求文件的完整路径 | /var/www/html/index.html |
| $status | 响应状态码 | 200、404、502 |
| $body_bytes_sent | 发送给客户端的字节数 | 1234 |
| $request_time | 请求处理时间(秒) | 0.052 |
8.3 条件判断详解
Nginx支持基于IP、User-Agent、Cookie等条件进行访问控制。
# 基于IP限制访问
location /admin/ {
allow 192.168.1.0/24; # 允许这个IP段
allow 10.0.0.0/8; # 允许这个IP段
deny all; # 拒绝其他所有IP
}
# 基于User-Agent限制(阻止爬虫)
if ($http_user_agent ~* "bot|spider|crawl") {
return 403; # 返回禁止访问
}
# 基于Cookie限制
if ($cookie_session ~* "invalid") {
return 403;
}
# 基于请求方法限制
location /api/ {
limit_except GET POST PUT DELETE { # 只允许这些方法
deny all; # 其他方法拒绝
}
}
8.4 速率限制详解
Nginx提供两种限流方式:请求速率限制(limit_req)和并发连接限制(limit_conn)。
| 概念 | 解释 |
|---|---|
| limit_req_zone | 定义限流区域(共享内存),存储请求计数 |
| $binary_remote_addr | 二进制格式的客户端IP(比$remote_addr更省内存) |
| rate | 速率,单位r/s(每秒请求数)或r/m(每分钟请求数) |
| burst | 突发允许的请求数 |
| nodelay | 不延迟处理突发请求 |
| limit_req_status | 超出限制时返回的状态码 |
# 定义请求速率限制区域(基于IP)
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
# 定义并发连接限制区域
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
server {
location /api/ {
# 应用限流:速率10r/s,突发允许20个请求,不延迟
limit_req zone=mylimit burst=20 nodelay;
limit_req_status 429; # 超限时返回429 Too Many Requests
}
location / {
# 限制每个IP最多10个并发连接
limit_conn connlimit 10;
limit_conn_status 429;
}
}
8.5 缓存配置详解
Nginx可以缓存后端服务器的响应,减少对后端的请求,提升响应速度。
| 概念 | 解释 |
|---|---|
| proxy_cache_path | 定义缓存存储路径和参数 |
| levels | 缓存目录层级深度(如1:2表示两级目录) |
| keys_zone | 缓存元数据共享内存区域(名称:大小) |
| max_size | 缓存最大磁盘空间 |
| inactive | 缓存有效期(不活跃时间后自动清除) |
| use_temp_path | 是否使用临时目录(off表示直接写入缓存) |
| proxy_cache | 启用的缓存区域名称 |
| proxy_cache_valid | 不同状态码的缓存时间 |
| proxy_cache_key | 缓存键的组成(决定缓存命中条件) |
| $upstream_cache_status | 缓存状态变量(HIT/MISS/EXPIRED等) |
# 定义代理缓存路径和参数
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
max_size=1g inactive=60m use_temp_path=off;
server {
location / {
proxy_pass http://backend;
# 启用缓存
proxy_cache my_cache; # 使用名为my_cache的缓存
# 缓存有效期(按状态码区分)
proxy_cache_valid 200 60m; # 200响应缓存60分钟
proxy_cache_valid 404 1m; # 404响应缓存1分钟
# 缓存键(决定缓存如何命中)
proxy_cache_key "$scheme$request_method$host$request_uri";
# 添加缓存状态头(方便调试)
add_header X-Cache-Status $upstream_cache_status;
}
}
9. 性能优化
9.1 Worker 进程配置详解
Worker进程是实际处理请求的进程,其配置直接影响Nginx并发性能。
| 概念 | 解释 |
|---|---|
| worker_processes | Master进程fork的Worker数量,auto表示自动设置为CPU核心数 |
| worker_cpu_affinity | 将Worker进程绑定到特定CPU核心,减少进程切换开销 |
| worker_rlimit_nofile | 单个Worker可打开的最大文件描述符数量 |
# 全局块
worker_processes auto; # 自动设置为CPU核心数
worker_cpu_affinity auto; # CPU绑定(Linux特有,减少进程切换)
# 每个Worker允许的连接数(需配合系统ulimit)
worker_rlimit_nofile 65535; # 最大文件描述符数
9.2 Events 块优化详解
Events块配置连接处理方式,对高并发性能至关重要。
| 概念 | 解释 |
|---|---|
| worker_connections | 单个Worker进程可处理的最大并发连接数 |
| use epoll | 使用epoll事件模型(Linux 2.6+,高效处理大量并发) |
| multi_accept | 一次accept()接受多个连接,减少系统调用 |
events {
worker_connections 65535; # 单个Worker最大连接数
use epoll; # Linux高效事件模型(BSD用kqueue)
multi_accept on; # 一次接受多个新连接
}
9.3 HTTP 块优化详解
HTTP块包含大量性能优化配置。
| 概念 | 解释 |
|---|---|
| sendfile | 启用零拷贝文件传输,减少内核态/用户态切换 |
| tcp_nopush | 在sendfile开启时,等待多个数据包后一起发送(减少包头开销) |
| tcp_nodelay | 禁用Nagle算法,降低小数据包的延迟 |
| keepalive_timeout | keep-alive连接保持时间 |
| keepalive_requests | 单个keep-alive连接可处理的最大请求数 |
| gzip | 启用gzip压缩,减小传输大小 |
| gzip_comp_level | 压缩级别(1-9,越高压缩率越高但CPU开销越大) |
| gzip_types | 需要压缩的MIME类型 |
| client_body_buffer_size | 客户端请求体缓冲区大小 |
| client_max_body_size | 客户端最大请求体大小(上传文件限制) |
| open_file_cache | 文件描述符缓存,减少磁盘IO |
http {
# 文件传输优化
sendfile on; # 零拷贝技术
tcp_nopush on; # 配合sendfile,攒包发送
tcp_nodelay on; # 禁用Nagle算法,降低延迟
# 连接优化
keepalive_timeout 65; # keep-alive超时(秒)
keepalive_requests 1000; # 单连接最大请求数
# 压缩配置
gzip on; # 启用gzip压缩
gzip_vary on; # 添加Vary头(代理缓存需)
gzip_proxied any; # 代理的响应也压缩
gzip_comp_level 6; # 压缩级别6(平衡压缩率和CPU)
gzip_types text/plain text/css text/xml application/json
application/javascript application/rss+xml application/atom+xml;
gzip_min_length 1000; # 只有大于1000字节才压缩
# 缓冲区配置
client_body_buffer_size 16k; # 请求体缓冲
client_header_buffer_size 1k; # 请求头缓冲
client_max_body_size 8m; # 最大请求体(上传限制)
large_client_header_buffers 4 8k; # 大请求头缓冲(数量 大小)
# 打开文件缓存(减少磁盘IO)
open_file_cache max=65535 inactive=20s; # 最大缓存文件数和不活跃时间
open_file_cache_valid 30s; # 缓存验证间隔
open_file_cache_min_uses 2; # 缓存文件的最小使用次数
open_file_cache_errors on; # 缓存文件不存在错误
}
9.4 FastCGI 优化(PHP)详解
FastCGI是Nginx与PHP通信的协议(php-fpm),需要合理配置缓冲区保持连接。
| 概念 | 解释 |
|---|---|
| fastcgi_pass | PHP-FPM的地址(可以是TCP端口或Unix socket) |
| fastcgi_keep_conn | 保持FastCGI连接复用,减少连接开销 |
| fastcgi_connect_timeout | 与PHP-FPM建立连接的超时时间 |
| fastcgi_send_timeout | 向PHP-FPM发送请求的超时时间 |
| fastcgi_read_timeout | 等待PHP-FPM响应的超时时间 |
| fastcgi_buffer_size | 读取响应头的缓冲区大小 |
| fastcgi_buffers | 响应体缓冲区(数量 大小) |
upstream php_backend {
server 127.0.0.1:9000;
keepalive 16; # 保持16个连接到PHP-FPM
}
server {
location ~ \.php$ {
fastcgi_pass php_backend;
fastcgi_keep_conn on; # 保持连接复用
# 超时配置
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
# 缓冲区配置
fastcgi_buffer_size 4k; # 响应头缓冲
fastcgi_buffers 8 4k; # 响应体缓冲(8个,每个4k)
fastcgi_busy_buffers_size 8k; # 忙碌时缓冲大小
fastcgi_temp_file_write_size 8k; # 写入临时文件大小
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
10. 故障排查
10.1 常用命令详解
| 命令 | 说明 | 使用场景 |
|---|---|---|
nginx -t |
测试配置语法是否正确 | 重载配置前必用 |
nginx -T |
测试配置并打印完整配置 | 调试include文件问题 |
nginx -s reload |
发送HUP信号重载配置 | 更新配置不中断服务 |
nginx -s stop |
发送TERM信号立即停止 | 强制停止 |
nginx -s quit |
发送QUIT信号优雅停止 | 等待请求处理完再停止 |
nginx -v |
显示版本号 | 查看版本 |
nginx -V |
显示版本、编译参数、配置参数 | 查看编译时选项 |
nginx -c |
指定配置文件路径 | 使用非默认配置启动 |
10.2 日志分析详解
Nginx有两大日志文件:
- access.log(访问日志):记录每个请求的详细信息
- error.log(错误日志):记录服务器错误和警告
# 实时查看访问日志(-f 跟踪文件变化)
sudo tail -f /var/log/nginx/access.log
# 实时查看错误日志
sudo tail -f /var/log/nginx/error.log
# 分析访问日志 - 统计最常访问的URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 分析访问日志 - 统计TOP IP(找出异常访问源)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 查找错误日志中的错误
grep -i error /var/log/nginx/error.log
# 分析慢请求(需在log_format中配置$request_time)
awk '{if($NF>1) print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -20
10.3 常见错误及解决方案详解
| HTTP状态码 | 错误名称 | 原因分析 | 解决方案 |
|---|---|---|---|
| 400 | Bad Request | 请求头过大、请求格式错误 | 增大large_client_header_buffers |
| 403 | Forbidden | 文件权限不足、SELinux限制、deny规则 | 检查文件权限、allow/deny规则 |
| 404 | Not Found | 文件不存在、root路径错误 |
检查root路径、try_files配置 |
| 502 | Bad Gateway | 后端服务器无响应、超时 | 检查后端服务、proxy_pass配置 |
| 503 | Service Unavailable | 后端服务器全挂、连接数满 | 检查后端健康状态、backup服务器 |
| 504 | Gateway Timeout | 后端响应超时 | 增加proxy_read_timeout |
| 413 | Request Entity Too Large | 上传文件过大 | 增加client_max_body_size |
| 499 | Client Closed Request | 客户端提前关闭连接 | 检查超时设置、客户端行为 |
10.4 压力测试详解
压力测试用于评估Nginx在高并发下的性能表现。
| 工具 | 说明 | 常用参数 |
|---|---|---|
| ab(Apache Bench) | Apache自带的简单压测工具 | -n总请求数,-c并发数 |
| wrk | 高性能HTTP压测工具 | -t线程数,-c连接数,-d持续时间 |
| siege | 多线程压测工具 | -c并发数,-t持续时间 |
# ab压测:10000个请求,100个并发
ab -n 10000 -c 100 http://localhost/
# wrk压测:12线程,400连接,持续30秒
wrk -t12 -c400 -d30s http://localhost/
# siege压测:100并发,持续30秒
siege -c 100 -t 30s http://localhost/
10.5 调试技巧详解
# 启用调试级别日志(记录最详细的日志信息)
error_log /var/log/nginx/error.log debug;
# 在特定location中记录详细访问日志
location / {
access_log /var/log/nginx/detail.log main;
body_log on; # 记录请求体
header_log on; # 记录请求头
}
# 模拟错误响应(测试监控告警)
location /test {
return 500 "Test Error";
}
📚 附录
A. 常用配置指令速查表
| 指令 | 说明 | 可用位置 |
|---|---|---|
| listen | 监听端口,可指定IP和端口,如80、0.0.0.0:80、443 ssl |
server |
| server_name | 服务器域名,支持精确匹配、通配符、正则表达式 | server |
| root | 文档根目录,定义网站文件的物理路径 | server, location |
| location | URL路由块,根据URI路径匹配并处理请求 | server |
| proxy_pass | 反向代理目标地址,转发请求到后端服务器 | location |
| proxy_set_header | 设置转发给后端的请求头(如Host、Client-IP等) | http, server, location |
| ssl_certificate | SSL证书文件路径(包含证书链) | server |
| ssl_certificate_key | SSL私钥文件路径 | server |
| rewrite | URL重写规则,可用于重定向或内部路由 | server, location |
| try_files | 依次尝试文件/目录,最后回退到指定URI或状态码 | location |
| error_page | 定义错误页面,当发生指定错误码时显示 | http, server, location |
| limit_req | 请求速率限制,控制每秒/每分钟请求数 | location |
| limit_conn | 并发连接数限制,控制单个IP的并发连接数 | location |
| gzip | 启用gzip压缩,减小传输大小 | http, server, location |
| add_header | 向响应添加自定义HTTP头部 | http, server, location |
| expires | 设置Cache-Control和Expires头,控制浏览器缓存时间 | http, server, location |
B. 参考资源
| 资源 | 说明 | 链接 |
|---|---|---|
| 📘 官方文档 | Nginx官方文档,最权威的技术参考 | https://nginx.org/en/docs/ |
| 📘 官方教程 | Nginx入门教程,适合初学者 | https://nginx.org/en/docs/beginners_guide.html |
| 📘 SSL配置指南 | Mozilla的SSL配置推荐(安全加固参考) | https://ssl-config.mozilla.org/ |
| 📘 Let's Encrypt | 免费SSL证书申请和管理 | https://letsencrypt.org/ |
| 📘 Certbot | Let's Encrypt官方客户端 | https://certbot.eff.org/ |
💡 提示:建议使用
nginx -t验证配置后再重载!🔐 安全提醒:生产环境务必启用 HTTPS,定期更新 SSL 证书!
📅 文档更新时间:2026/05/18

浙公网安备 33010602011771号