--- title: Nginx tags: [概念, nginx, web-server, 负载均衡, 反向代理, stream 模块, web, network] created: 2026-07-21 updated: 2026-08-12 sources:
- raw/day28 快速构建集群架构.md
- raw/day33 负载均衡层详解part1.md
- raw/day34 负载均衡层详解part2.md
- raw/day25 Shell编程6.md
- raw/一、nginx详解 – Egon林海峰.md
- raw/day44 nginx详解part4.md
- raw/day41 nginx详解part1.md
- raw/day42 nginx详解part2.md
- raw/day43 nginx详解part3.md
- raw/day45 nginx详解part5.md
- raw/nginx优化上 – Egon林海峰.md
- raw/nginx优化下 – Egon林海峰.md
- raw/day47 ssl、tls及全站https.md aliases: [Nginx, 引擎-x, Igor Sysoev, OpenResty]
Nginx
Nginx(发音 “engine-x”)是一款开源的高性能 Web 服务器,同时具备反向代理和负载均衡能力,由俄罗斯程序员 Igor Sysoev 开发。在集群架构中,Nginx 遍布多个层级,是最核心的基础设施组件之一。
核心能力
1. 七层负载均衡(http 模块)
工作于 OSI 第七层(应用层),解析 HTTP 协议内容进行精细化路由:
- 按 URL 路径(
/api/*→ API 集群,/static/*→ 静态文件服务器) - 按域名(
Host: blog.example.com→ 博客集群) - 按 Cookie、User-Agent 等头部信息
- 支持
proxy_pass反向代理 +upstream后端服务器池
http {
upstream web_servers {
server 192.168.71.112:8080 weight=1;
server 192.168.71.113:8080 weight=1;
}
server {
listen 8081;
location / {
proxy_pass http://web_servers;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}2. 四层负载均衡(stream 模块)
工作于 OSI 第四层(传输层),基于 IP+Port 转发 TCP/UDP 流量:
- 代理 MySQL、Redis 等非 HTTP 协议
- 四层代理七层放大并发(四层粗分发 → 七层细分发)
- 配置语法:
stream { upstream {} server { listen; proxy_pass; } }
stream {
upstream l7_servers {
server 192.168.71.116:8081;
server 192.168.71.111:8081;
}
server {
listen 9999;
proxy_pass l7_servers;
}
}3. 静态文件服务 + 反向代理
集群架构中的典型位置:
用户 → LVS(四层)→ Nginx(七层,动静分离)→ 应用服务器
→ 静态文件直接返回
4. 协议透传
- 七层:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for - 四层:配合 Proxy Protocol(HAProxy 协议)透传客户端 IP
与其他方案对比
| 方案 | 层级 | 性能 | 功能 | 适合场景 |
|---|---|---|---|---|
| LVS | 四层 | ⭐⭐⭐ | ⭐ | 大规模集群入口 |
| Nginx | 四/七层 | ⭐⭐ | ⭐⭐⭐ | Web 七层负载均衡首选 |
| Haproxy | 四/七层 | ⭐⭐ | ⭐⭐ | 精细 ACL 路由 |
| F5 | 四/七层 | ⭐⭐⭐ | ⭐⭐⭐ | 金融/运营商(昂贵) |
关键配置要点
worker_processes:CPU 核心数worker_connections:每个 worker 最大连接数worker_rlimit_nofile:文件描述符上限(高并发必须调高)proxy_connect_timeout/proxy_timeout:后端连接超时max_fails/fail_timeout:健康检查参数
安装方式
| 方式 | 命令 | 优点 | 适用场景 |
|---|---|---|---|
| Yum 安装 | yum install nginx | 快速便捷,包管理 | 测试环境、快速部署 |
| 源码编译 | ./configure && make && make install | 可定制编译参数,模块自由选择 | 生产环境、定制需求 |
Yum 安装文件分散在系统目录;源码安装文件集中在 --prefix 指定目录,便于管理。
源码常见编译参数:
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-stream \
--with-http_v2_module \
--with-threads依赖:gcc pcre-devel openssl-devel zlib-devel
文件分布(Yum 安装)
| 路径 | 用途 |
|---|---|
/etc/nginx/nginx.conf | 主配置文件 |
/etc/nginx/conf.d/ | 子配置文件目录(通过 include 加载) |
/etc/nginx/fastcgi_params | FastCGI 协议参数 |
/etc/nginx/uwsgi_params | uWSGI 协议参数 |
/etc/nginx/mime.types | MIME 类型映射 |
/usr/sbin/nginx | 管理命令 |
/var/log/nginx/ | 日志文件(access.log、error.log) |
/etc/logrotate.d/nginx | 日志轮转配置 |
常用命令与平滑升级
| 命令 | 说明 |
|---|---|
nginx -t | 检查配置文件语法 |
nginx -T | 检查并输出完整配置 |
nginx -s reload | 热重载配置(不重启进程) |
nginx -s stop | 快速停止 |
nginx -s quit | 优雅停止(处理完当前请求后退出) |
nginx -s reopen | 重新打开日志文件 |
nginx -v / nginx -V | 查看版本 / 版本+编译参数 |
平滑升级:将新版本 Nginx 编译安装到独立目录 → 切换软链接 → 发送 USR2 信号启动新 master → 发送 QUIT 信号让旧 master 优雅退出。
配置结构
Nginx 配置采用分块层级结构:
main(全局块)
├── events 块(网络IO模型)
├── http 块(HTTP 协议相关)
│ ├── upstream 块(后端服务器池)
│ ├── server 块(虚拟主机)
│ │ └── location 块(URL 匹配与处理)
│ └── ...
└── stream 块(四层 TCP/UDP 代理)
└── server 块
http 块关键指令
| 指令 | 作用 |
|---|---|
sendfile | 零拷贝文件传输 |
tcp_nopush / tcp_nodelay | TCP 性能优化 |
keepalive_timeout | 长连接超时 |
types_hash_max_size | MIME 类型哈希表大小 |
default_type | 默认 Content-Type |
server 块(虚拟主机)
listen:监听 IP:端口server_name:域名匹配(精确/通配符/正则)index:默认索引文件(按顺序查找)error_page:自定义错误页
Events 配置与网络 IO 模型
events 块配置 Nginx 连接处理方式。Nginx 采用 epoll 异步非阻塞事件驱动模型,是其高并发能力的核心。
网络 IO 模型对比
| 模型 | 机制 | 效率 | 适用场景 |
|---|---|---|---|
| select | 遍历所有连接检查数据到达 | 连接越多效率越低 | 连接 < 1024 |
| poll | 类似 select,无连接数限制 | 大量连接仍低效 | 连接数稍多 |
| epoll | 每个 IO 绑定回调,数据到达时主动触发 | 连接越多优势越明显 | 高并发场景 |
并发量计算
最大并发 ≈ worker_processes × worker_connections
worker_processes:工作进程数,通常设为 CPU 核心数worker_connections:每个 worker 的最大连接数- 需结合硬件资源(CPU/内存)和系统文件描述符限制(
ulimit -n)设置
events 配置示例
events {
use epoll; # 使用 epoll 模型
worker_connections 1024; # 每进程最大连接数
multi_accept on; # 单次 accept 可接受多个连接
}HTTP 核心优化参数
文件传输
| 参数 | 说明 | 推荐值 |
|---|---|---|
sendfile on; | 零拷贝:文件直接从内核缓冲区到网卡,绕过用户态 | on |
tcp_nopush on; | 与 sendfile 配合,数据包填满后再发送 | on |
tcp_nodelay on; | 禁用 Nagle 算法,小块数据实时发送 | on |
传统传输:硬盘 → 内核缓冲区 → 用户态缓冲区 → 内核缓冲区 → 网卡
sendfile:硬盘 → 内核缓冲区 → 网卡(零拷贝)
连接与超时
| 参数 | 说明 | 推荐值 |
|---|---|---|
keepalive_timeout | 长连接超时时间 | 65s |
keepalive_requests | 单连接最大请求数 | 100 |
client_max_body_size | 客户端请求体最大大小 | 1m |
client_header_timeout | 请求头超时 | 60s |
client_body_timeout | 请求体超时 | 60s |
reset_timedout_connection on; | 超时后重置连接 | on |
文件缓存
open_file_cache max=1000 inactive=20s; # 打开文件缓存
open_file_cache_valid 30s; # 缓存有效期
open_file_cache_min_uses 2; # 最少使用次数
open_file_cache_errors on; # 缓存错误信息Gzip 压缩
gzip on; # 启用压缩
gzip_min_length 1k; # 最小压缩大小
gzip_comp_level 6; # 压缩级别(1-9)
gzip_types text/plain text/css application/json application/javascript text/xml;Server 与虚拟主机
虚拟主机指通过一个 Nginx 承载多个站点,每个站点对应一个 server 块。
三种实现方式
| 方式 | 配置依据 | 适用场景 |
|---|---|---|
| 基于域名 | server_name | 最常用,多域名共享同一 IP:端口 |
| 基于端口 | listen 不同端口 | 不同服务使用不同端口 |
| 基于 IP | 不同 IP 地址 | 服务器有多个 IP |
# 基于域名(最常用)
server {
listen 80;
server_name www.site1.example.com;
root /var/www/html/site1;
}
server {
listen 80;
server_name www.site2.example.com;
root /var/www/html/site2;
}
server {
listen 80 default_server; # 默认站点(未匹配时使用)
server_name _;
root /var/www/html/default;
}Location 匹配规则
location 是 Nginx 配置中最核心的模块,决定了请求如何路由到不同的处理逻辑。
匹配优先级(从高到低)
| 优先级 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 1(最高) | = uri | = /logo.png | 精确匹配,命中即停止 |
| 2 | ^~ uri | ^~ /static/ | 前缀匹配,命中后不再检查正则 |
| 3 | ~ pattern | ~ \.php$ | 正则匹配(区分大小写),按定义顺序 |
| 4 | ~* pattern | ~* \.jpg$ | 正则匹配(不区分大小写) |
| 5(最低) | uri | / / /api/ | 普通前缀匹配,取最长匹配 |
匹配完整流程
① 先检查精确匹配(=)
├─ 命中 → 直接使用,停止
└─ 未命中 → 进入第②步
② 检查前缀匹配(^~ 和普通前缀)
├─ 记录最长前缀匹配
├─ 如果有 ^~ 命中 → 跳过正则检查,使用该 location
└─ 否则 → 进入第③步
③ 按定义顺序检查正则匹配(~ / ~*)
├─ 命中第一个正则 → 使用该 location
└─ 全部未命中 → 使用第②步记录的最长前缀
命名 location
location @name { ... } 形式,用于内部重定向(类似 goto),不对外暴露。
日志配置
访问日志(access_log)
# 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# json 格式(便于日志收集系统解析)
log_format json escape=json '{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"http_x_forwarded_for":"$http_x_forwarded_for"'
'}';
# 应用日志格式
access_log /var/log/nginx/access.log main buffer=32k flush=5s;| 参数 | 说明 |
|---|---|
buffer=32k | 缓冲区大小,满后写入磁盘 |
flush=5s | 缓冲区超时刷出 |
gzip | 实时压缩后写入 |
错误日志(error_log)
error_log /var/log/nginx/error.log warn; # 级别:debug < info < notice < warn < error < crit < alert < emerg生产环境通常设置为 warn 或 error。
日志轮转(logrotate)
日志文件不断增长,需定期切割归档。通过 /etc/logrotate.d/nginx 配置:
/var/log/nginx/*.log {
daily # 每天轮转
rotate 52 # 保留 52 份
compress # 压缩旧日志
delaycompress # 延迟压缩
notifempty # 空文件不轮转
create 644 nginx nginx
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid` # 通知 Nginx 重开日志文件
fi
endscript
}或手动:nginx -s reopen 重新打开日志文件句柄。
root vs alias
两个指令都用于将 URI 映射到文件系统路径,但行为关键不同:
| 指令 | 行为 | 示例 |
|---|---|---|
root | 拼接:root 路径 + location 路径 | root /var/www/html + /user/ → /var/www/html/user/ |
alias | 替换:直接用 alias 路径替代 | alias /mmm/ + / → /mmm/(不拼接) |
alias 末尾必须加斜杠(
/),否则路径拼接异常。
return 指令
用于停止处理请求,直接返回状态码或重定向。
语法
return code [text]; # 返回状态码 + 响应体
return code URL; # 重定向到 URL
return URL; # 需以 http:// 或 https:// 开头301 vs 302
| 对比项 | 301 永久重定向 | 302 临时重定向 |
|---|---|---|
| 浏览器缓存 | 缓存结果,后续直接走新地址 | 不缓存,每次都请求原地址 |
| 服务器压力 | 仅第一次请求 | 每次请求都到服务器 |
| SEO 影响 | 权重转移 | 权重不转移 |
| 适用场景 | 域名永久迁移、HTTP→HTTPS | 临时活动页、AB 测试、维护中跳转 |
使用建议:简单跳转优先用 return(比 rewrite 性能更好)。HTTPS 跳转用 301,临时活动页用 302。
HTTPS / SSL 配置
HTTPS = HTTP + SSL/TLS。Nginx 作为 SSL 终结端,在 server 块配置证书与加密参数,支持单节点与集群全站加密。加密原理、证书体系与认证流程详见 SSL/TLS 与 HTTPS 加密体系。
单节点 HTTPS 配置
server {
listen 443 ssl http2;
server_name example.com;
# 证书配置(Certbot/Let's Encrypt 申请)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 协议与加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# HSTS(强制浏览器始终使用 HTTPS)
add_header Strict-Transport-Security "max-age=31536000" always;
root /var/www/html;
index index.html;
}HTTP 自动跳转 HTTPS
server {
listen 80;
server_name example.com;
# 301 永久重定向到 HTTPS
return 301 https://$server_name$request_uri;
}全站 HTTPS(集群架构)
全站 HTTPS = 每一层通信都加密:用户 → 七层 LB(HTTPS)→ Web 层 → FastCGI → php-fpm → MySQL SSL。
七层负载均衡器 HTTPS 配置(代理到 Web 集群,透传原始协议):
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
location / {
proxy_pass http://web_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}FastCGI + HTTPS(PHP 应用):后端代码需判断请求是否 HTTPS 时,传递 HTTPS 环境变量:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 传递 HTTPS 标识给 PHP
fastcgi_param HTTPS on;
fastcgi_param HTTP_SCHEME https;
include fastcgi_params;
}SSL 参数速查
| 参数 | 说明 |
|---|---|
ssl_certificate | 证书文件路径(含完整证书链) |
ssl_certificate_key | 私钥文件路径 |
ssl_protocols | 支持的 TLS 协议版本 |
ssl_ciphers | 允许的加密套件 |
ssl_prefer_server_ciphers | 优先使用服务端加密套件顺序 |
HSTS(Strict-Transport-Security) | 强制浏览器在未来指定时间内始终使用 HTTPS |
代理类型
| 类型 | 代理对象 | 客户端配置 | 位置要求 | 典型用途 |
|---|---|---|---|---|
| 正向代理 | 客户端 | 需要 | 内/外网均可 | 翻墙、访问限制 |
| 透明代理 | 客户端(对用户透明) | 不需要 | 必须与客户端同内网 | 上网行为分析、内容过滤 |
| 反向代理 | 服务端 | 不需要 | 服务端前置 | 负载均衡、安全防护、缓存 |
Nginx 主要提供反向代理功能。
动静分离
通过 location 将动态请求和静态请求分开处理。分离和分层都是优化思想——核心思路是:能不能抽离出来?能抽离就能单独针对性地优化。
三大方案对比
| 方案 | 实施位置 | 优点 | 缺点 |
|---|---|---|---|
| 方案一 | 前端代码 | CDN 加速效果最好 | 需修改代码,更新需刷新 CDN |
| 方案二 | Web 服务器 | 精细化管理,缓存控制灵活 | Web 服务器仍承担部分静态流量 |
| 方案三-1 | 七层负载均衡器 | 动静分离彻底 | 负载均衡器职责不清(既派活又干活) |
| 方案三-2 | 七层负载均衡 + 独立集群 | 职责清晰,可独立扩展 | 架构复杂,成本较高 |
推荐组合:方案一(CDN 加速前端静态资源)+ 方案二(Web 服务器层精细缓存 + expires)+ 方案三-2(LB 层抽离到独立静态集群)。
方案一:前端代码直接使用 CDN 地址
后端返回前端代码时,静态文件 URL 直接配置为 CDN 地址:
<img src="https://cdn.example.com/static/img/logo.jpg">
<link rel="stylesheet" href="https://cdn.example.com/static/css/style.css">方案二:Web 服务器层分离
server {
listen 80;
root /var/www/html;
# 动态请求:转发给 php-fpm
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
}
# 静态请求:Nginx 直接返回,设置缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
access_log off;
}
}方案三:七层负载均衡层分离
upstream app_servers {
server 192.168.43.100:8080;
server 192.168.43.101:8080;
}
upstream static_servers {
server 192.168.43.200:80;
server 192.168.43.201:80;
}
server {
listen 80;
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_pass http://static_servers;
expires 30d;
}
location / {
proxy_pass http://app_servers;
}
}Web 服务器层分离(基础形式)
location / {
proxy_pass http://web_servers; # 动态请求 → 应用服务器
}
location /static/ {
root static; # 静态请求 → 本地文件
}资源分离
动静分离的进一步细化——根据请求特征(如 User-Agent、URL 参数等)将请求分发到不同后端集群:
upstream android { server 10.0.0.7:80; }
upstream iphone { server 10.0.0.8:80; }
upstream pc { server 10.0.0.9:80; }
server {
listen 80;
server_name example.com;
location / {
if ($http_user_agent ~* "Android") { proxy_pass http://android; }
if ($http_user_agent ~* "iPhone") { proxy_pass http://iphone; }
if ($http_user_agent ~* "WOW64") { return 403; }
proxy_pass http://pc; # 默认走 PC 集群
}
}常用于移动端/PC 端分离、灰度发布等场景。
TCP 连接队列
半连接队列与全连接队列
在 TCP 三次握手过程中,内核为每个监听 socket 维护两个队列:
| 队列 | 状态 | 存储内容 | 内核参数 |
|---|---|---|---|
| 半连接队列(SYN Queue) | SYN_RECV | 已发 SYN+ACK 等待第三次握手 | net.ipv4.tcp_max_syn_backlog |
| 全连接队列(Accept Queue) | ESTABLISHED | 三次握手完成,等待 accept() | net.core.somaxconn |
队列满的后果:半连接队列满 → 新 SYN 被丢弃;全连接队列满 → 新连接被丢弃或客户端超时。
SYN Flood 攻击:攻击者大量发 SYN 不回复 ACK,占满半连接队列。通过 net.ipv4.tcp_syncookies = 1 启用 SYN Cookie 防御。
Nginx 全连接队列两种模式
模式一:共享全连接队列(默认)
所有 worker 进程从同一个全连接队列中通过 accept() 取连接。优点:某个 worker 处理耗时请求时,其他 worker 仍能取新连接,压力自动平衡。缺点:多 worker 并发争抢需加锁,有性能损耗。
模式二:独享全连接队列(reuseport)
每个 worker 进程独立调用 bind() + listen(),拥有独立的全连接队列。内核根据四元组哈希将连接分发到各 worker,无需加锁。
server {
listen 80 reuseport backlog=4096; # 开启 reuseport
}优点:减少锁竞争,处理效率更高。缺点:某个 worker 繁忙时,其他 worker 无法分担其队列压力。
Worker 内多线程
通过 --with-threads 编译选项支持,配置 aio threads; 开启。好处:缓解 worker 繁忙时的压力;坏处:引入线程间资源争抢,增加 bug 风险。
Nginx 抗并发优化路径
默认模式(共享队列 + 单线程 worker)
→ 开启 reuseport(独享队列,减少锁竞争)
→ 开启 threads(多线程 worker,进一步提升并发)
Upstream 健康检查与负载均衡
健康检查参数
| 参数 | 说明 |
|---|---|
max_fails=3 | 连续失败最大次数,超过后标记不可用 |
fail_timeout=5s | 超时时间内累计 max_fails 次则不可用 |
backup | 备用服务器 |
down | 手动下线 |
upstream my_servers {
server 192.168.43.100:8080 max_fails=3 fail_timeout=5s;
server 192.168.43.101:8080 max_fails=3 fail_timeout=5s;
server 192.168.43.102:8080 backup;
server 192.168.43.103:8080 down;
}双重故障检测
- 端口级:
max_fails + fail_timeout检测进程挂掉、网络不通 - 应用层:
proxy_next_upstream检测后端进程存在但返回错误响应
location / {
proxy_pass http://my_servers;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_403 http_404;
}慢启动(slow_start)
新服务器瞬间接收大量流量可能打满连接池。slow_start 让新服务器逐步接收流量(Nginx Plus 支持,开源版不支持)。
Nginx 开源版替代方案:流量低峰期上线、手动逐步增加权重、或使用 Haproxy(原生支持 slow_start)。
负载均衡算法
| 算法 | 说明 | 适用场景 |
|---|---|---|
| 轮询(默认) | 按顺序轮流分发 | 后端配置相同 |
weight | 按权重比例分发 | 后端性能不同 |
ip_hash | 按客户端 IP 哈希,同一 IP 固定到同一服务器 | 会话保持 |
least_conn | 分发到当前连接数最少的服务器 | WebSocket 长连接 |
url_hash | 按 URL 哈希分发 | 缓存服务器提高命中率 |
Rewrite 重写模块
ngx_http_rewrite_module 提供 URI 改写功能,将请求 URI 中的路径部分改写为新的路径。
应用场景
| 场景 | 说明 |
|---|---|
| 伪静态 | 将动态 URL 转为静态路径格式,方便搜索引擎收录 |
| 协议/端口更换 | HTTP → HTTPS,端口重写 |
| 域名迁移 | 旧域名的访问跳转到新域名 |
五种控制指令
| 指令 | 作用 | 类比 |
|---|---|---|
break | 终止循环,不再执行后续重写规则 | 循环中的 break |
last | 终止本次循环,重新开始新一轮 location 匹配 | 循环中的 continue |
if | 条件判断 | 编程语言中的 if |
return | 返回状态码或重定向,整体结束 | 函数返回 |
rewrite | 将 URL 路径重写为新路径 | URL 改写 |
执行流程
① 请求到达
↓
② 执行 server 块中的重写规则
├─ 重写为完整 URL(带域名)→ 直接跳转
└─ 重写为纯路径 → 进入 loop 循环
↓
③ Loop 循环(最多 10 次,防死循环)
├─ 执行 location 块中的重写规则
├─ 匹配到新 location → 继续执行新 location 的重写规则
└─ 不匹配 → 结束循环
↓
④ 请求处理结束
rewrite 指令详解
语法:rewrite regex replacement [flag];
| 参数 | 说明 |
|---|---|
regex | 正则表达式,匹配请求 URI |
replacement | 替换后的路径或完整 URL |
flag | 可选标志,控制重写后的行为 |
四种 Flag:
| Flag | 说明 | 类比 |
|---|---|---|
break | 终止循环,不再执行后续重写规则 | 循环 break |
last | 终止本次循环,重新进行 location 匹配 | 循环 continue |
redirect | 返回 302 临时重定向 | 302 状态码 |
permanent | 返回 301 永久重定向 | 301 状态码 |
配置示例
server {
listen 80;
# break:终止循环,直接返回文件
location /break/ {
rewrite ^/break/(.*) /static/$1 break;
}
# last:重新进行 location 匹配
location /last/ {
rewrite ^/last/(.*) /static/$1 last;
}
location /static/ {
root /var/www/static;
}
# redirect:302 临时重定向(URL 栏会变)
location /old {
rewrite ^/old(.*) /new$1 redirect;
}
# permanent:301 永久重定向(浏览器缓存结果)
location /http {
rewrite ^/(.*) https://$server_name/$1 permanent;
}
}rewrite vs return
| 对比项 | rewrite | return |
|---|---|---|
| 功能 | URL 路径改写 | 返回状态码/重定向 |
| 正则支持 | 支持 | 不支持 |
| 性能 | 稍慢(需正则匹配) | 更快 |
| 适用场景 | 复杂的 URL 重写 | 简单的跳转 |
生产场景中简单的域名跳转优先使用 return(性能更好)。
伪静态案例
# 将 /article/123 映射到 /article.php?id=123
location / {
rewrite ^/article/(\d+)$ /article.php?id=$1 last;
}调试
rewrite_log on;
error_log /var/log/nginx/error.log notice;重写日志会记录到 error_log 中。
其他常用模块
| 模块 | 功能 | 配置示例 |
|---|---|---|
| 目录索引 | 自动生成目录列表 | autoindex on; |
| 访问控制 | 基于 IP 的访问限制 | allow 192.168.1.0/24; deny all; |
| 访问认证 | HTTP 基本认证 | auth_basic "Restricted"; auth_basic_user_file .htpasswd; |
| 状态监控 | 查看 Nginx 连接状态 | stub_status on; |
| 连接限制 | 限制同一 IP 并发连接数 | limit_conn addr 10; |
| 请求限制 | 限制请求频率 | limit_req zone=req burst=20 nodelay; |
配置示例
# 目录索引
location /download/ {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
# 访问控制
location /admin/ {
allow 192.168.1.0/24;
deny all;
}
# 访问认证
location /secret/ {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
# 状态监控
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
# 连接限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
location / {
limit_conn addr 10; # 同一 IP 最多 10 个并发连接
}
# 请求限制
limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
location / {
limit_req zone=req burst=20 nodelay; # 每秒最多 10 个请求,突发 20 个
}架构优化思路
整套架构追求四大目标:高性能、高可用、高一致性、安全性。
优化三步法
第一步:摸清情况
├─ 画架构图/链路图
└─ 了解业务特点(电商→峰值流量大;ToB→逻辑复杂 bug 率高)
第二步:发现瓶颈
├─ 计算类:峰值 QPS / 单机极限 QPS = 需要的机器数
└─ 观察类:MySQL 慢查询日志、top、netstat、stub_status
第三步:针对性优化
├─ 高频读 → 少读 / 就近读 / 读缓存
├─ 高频写 → 少写 / 漏斗写 / buffer 写
└─ 动静分离 / 冷热分离
核心思想:“细分问题 → 抽离成单独层 → 单独处理”。动静分离、冷热分离都是这一思想的体现。
分层优化方向
| 层级 | 常见问题 | 优化方向 |
|---|---|---|
| 数据库层 | 慢查询、IO 瓶颈 | 优化 SQL、加索引、引入 Redis 缓存 |
| Web 应用层 | 机器数不足、负载不均 | 扩容、调整权重 |
| 负载均衡层 | 内存/CPU 瓶颈 | 多级负载均衡、硬件 F5 |
| 文件服务器层 | 单点故障、性能不足 | 分布式存储(Ceph) |
| 网络层 | 丢包、延迟、带宽不足 | 优化网络、加带宽、CDN |
单机通用优化
| 维度 | 优化要点 |
|---|---|
| 硬件 | 负载均衡器(大内存多核)、数据库(大内存+SSD)、缓存(大内存) |
| 系统 | 内核参数调优(ipv4、半连接/全连接队列) |
| 软件 | 服务配置优化(Nginx)、应用环境参数调优 |
系统与 Nginx 优化
系统层面(内核参数)
| 参数 | 作用 | 配置 |
|---|---|---|
| 文件描述符 | 提高最大打开文件数 | ulimit -n 65535 |
| 半连接队列 | 增大 SYN 队列 | net.ipv4.tcp_max_syn_backlog = 16384 |
| 全连接队列 | 增大 accept 队列 | net.core.somaxconn = 16384 |
| TIME_WAIT 复用 | 快速回收端口 | net.ipv4.tcp_tw_reuse = 1 |
| 端口范围 | 增大可用端口 | net.ipv4.ip_local_port_range = 4000 65000 |
完整内核参数清单(/etc/sysctl.conf):
| 参数 | 值 | 作用 |
|---|---|---|
net.ipv4.tcp_fin_timeout | 2 | 快速释放 FIN_WAIT 连接 |
net.ipv4.tcp_tw_reuse | 1 | 复用 TIME_WAIT 端口 |
net.ipv4.tcp_tw_recycle | 1 | 快速回收 TIME_WAIT(NAT 环境慎用) |
net.ipv4.tcp_syncookies | 1 | 开启 SYN Cookie 防洪水攻击 |
net.ipv4.tcp_keepalive_time | 600 | 长连接探活间隔 |
net.ipv4.tcp_max_syn_backlog | 16384 | 半连接队列 |
net.ipv4.tcp_max_tw_buckets | 36000 | TIME_WAIT 桶上限 |
net.ipv4.tcp_syn_retries | 1 | SYN 重传次数 |
net.core.somaxconn | 16384 | 全连接队列 |
net.core.netdev_max_backlog | 16384 | 网卡收包队列 |
net.ipv4.ip_local_port_range | 4000 65000 | 本地端口范围 |
vim /etc/sysctl.conf # 写入后生效
sysctl -p文件描述符: 写入 /etc/security/limits.d/*.conf(优先级高于 /etc/security/limits.conf,无需重启,重新登录生效):
cat > /etc/security/limits.d/k8s.conf <<'EOF'
* soft nofile 65535
* hard nofile 131070
EOF
# soft:超过时提示;hard:超过时直接限制
ulimit -Sn # 查看软限制
ulimit -Hn # 查看硬限制
lsof | wc -l # 查看已打开的句柄数Nginx 层面
| 参数 | 作用 | 推荐配置 |
|---|---|---|
worker_processes | worker 进程数 | auto(与 CPU 核数一致) |
worker_connections | 每进程最大连接数 | 10240 |
worker_rlimit_nofile | 文件描述符上限 | 65535 |
use epoll | IO 模型 | epoll |
sendfile | 零拷贝 | on |
tcp_nopush | 大包发送(与 sendfile 配合) | on |
tcp_nodelay | 禁 Nagle 算法,低延迟 | on |
keepalive_timeout | 长连接超时 | 65 |
keepalive_requests | 单连接最大请求数 | 100 |
gzip | 压缩传输 | on |
client_max_body_size | 请求体大小 | 20m |
client_header_buffer_size | 请求头缓冲区 | 128k |
large_client_header_buffers | 大请求头缓冲区 | 4 128k |
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 10240;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;
gzip on;
client_max_body_size 20m;
client_header_buffer_size 128k;
large_client_header_buffers 4 128k;
}线程池 + reuseport(server 块)
thread_pool nginx_pool threads=3 max_queue=1024; # 全局定义线程池
http {
aio threads=nginx_pool; # 启用线程池
server {
listen 8089 reuseport backlog=10240; # reuseport 与线程池不冲突
}
}Nginx 代理长连接优化
反向代理默认每个请求都新建后端连接,性能开销大。通过长连接复用减少握手。
负载均衡代理到 Web 后端
upstream tomcat {
server 172.16.1.7:8080;
keepalive 8; # 每个 worker 保留 8 个空闲后端连接
}
server {
listen 80;
location / {
proxy_pass http://tomcat;
proxy_http_version 1.1; # 必须 HTTP/1.1 才支持长连接
proxy_set_header Connection ""; # 清除 Connection 头,启用复用
include proxy_params;
}
}Nginx 代理到 PHP-FPM
location ~* \.php$ {
fastcgi_pass php_server;
fastcgi_keep_conn on; # 开启与 PHP-FPM 的长连接
include fastcgi_params;
}proxy_params 标准配置
# /etc/nginx/proxy_params
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
proxy_next_upstream http_500 http_502 http_503 http_504;静态资源缓存机制
缓存相关 HTTP 头
响应头:
| 头 | 作用 |
|---|---|
Cache-Control: max-age=604800 | 最直接影响缓存策略;no-cache/no-store 表示不缓存 |
Expires: Tue, 11 Jun 2024 10:05:12 GMT | 过期时间;与 Cache-Control 并存时 Cache-Control 优先 |
Last-Modified | 资源最后修改时间 |
ETag | 资源唯一标识符 |
请求头:
| 头 | 作用 |
|---|---|
If-Modified-Since | 值来自 Last-Modified,服务端比对未修改则返回 304 |
If-None-Match | 值来自 ETag,与服务端文件 ETag 比对相同则返回 304 |
浏览器缓存流程
① 优先看响应头 cache-control
├─ 设置了缓存时间且未过期 → 直接用缓存
├─ no-cache → 继续看 expires
└─ 未设置 → 走 ETag 验证
② ETag:放入 If-None-Match 发往服务端比对
├─ 相同 → 304 Not Modified → 浏览器用缓存
└─ 不同 → 走 Last-Modified
③ Last-Modified:放入 If-Modified-Since 比对
├─ 相同 → 走缓存
└─ 不同 → 重新拉取
ETag 优先于 If-Modified-Since 被检测,因为 ETag 可解决 Last-Modified 时间精度问题(无法判断内容微小修改)。
Nginx 配置
# 配置缓存过期时间
location ~* \.(png|jpg|gif)$ {
root /code/cache;
expires 7d;
}
# 强制不走缓存
location ~* \.(png|jpg|gif)$ {
etag off;
add_header Cache-Control no-cache;
if_modified_since off;
}静态资源压缩
location ~* \.(png|jpg|gif)$ {
gzip on;
gzip_types image/jpeg image/gif image/png;
gzip_comp_level 9; # 图片也可压缩(1-9 级)
}防盗链
防止其他网站未经授权直接引用本站资源(图片、视频等),通过检查 HTTP 请求头中的 Referer 字段实现。核心原理:检测 Referer 字段判断请求来源。
注意:
curl -e伪造 Referer 可绕过防盗链——防盗链防的是 img 标签直接引用(盗链网站用<img src>指向本站资源),不是反爬虫。
valid_referers 语法
valid_referers none | blocked | server_names | string ...;| 参数 | 含义 |
|---|---|
none | 匹配无 Referer 头的请求(地址栏直接访问、收藏夹) |
blocked | 匹配被防火墙/代理删除、或被修改为 - 的 Referer |
server_names | 匹配当前 server 块定义的 server_name |
string | 自定义特定域名,*.example.com 匹配子域名 |
配置示例
location ~* \.(jpg|jpeg|png|gif|ico)$ {
valid_referers none blocked server_names
*.example.com example.com;
if ($invalid_referer) {
return 403;
# 或返回防盗链提示图片
# rewrite ^/.*$ /static/anti-hotlink.jpg break;
}
expires 30d;
}$invalid_referer 变量:合法为 0,非法为 1。允许特定域名盗链:valid_referers none blocked server_names *.baidu.com;(多加一个域名)。
允许跨域
跨域问题根源:浏览器同源策略——协议、域名、端口三者任一不同,浏览器会阻止请求。同源策略不限制跨域请求的发送,而是丢弃跨域请求的响应包。目标站点可通过响应头声明”我允许这个跨域请求”,浏览器就会放行响应。
前后端分离架构(前端和后端独立部署,通过 API 通信)是跨域的主要场景。
前后端开发模式
| 模式 | 代码形态 | 优点 | 缺点 |
|---|---|---|---|
| 前后端混合 | 前后端同包,一个端口 | 部署简单、开发初期快 | 耦合高、无法兼容多端 |
| 前后端分离 | 前端静态包 + 后端 API | 解耦、多端复用、独立扩展 | 需处理跨域、约定 API |
分离部署的两种方式
同域部署(Nginx 统一代理,最常见):前端静态文件与后端 API 走同一域名,Nginx 按路径分发——/ 返回静态文件,/api 转发后端。无跨域问题、后端监听内网不暴露公网,适合中小项目;缺点 Nginx 单点故障、流量集中。
server {
listen 80;
server_name myapp.com;
location / {
root /var/www/html/; # 前端静态文件
index index.html;
}
location /api {
proxy_pass http://内网地址:3000; # 后端 API
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}跨域部署(前后端独立域名):前端 front.myapp.com(CDN/Nginx 静态)、后端 api.myapp.com,后端必须配置 CORS。完全解耦、前端可上 CDN 独立扩展,适合大型项目;缺点需双域名+CORS+证书、后端暴露公网需额外防护。
| 对比项 | 同域部署 | 跨域部署 |
|---|---|---|
| 部署复杂度 | 较低 | 较高(双域名+CORS+证书) |
| 跨域问题 | 无 | 需后端配置 CORS |
| 扩展性 | 耦合高,整体扩展 | 耦合低,独立扩展 |
| 适用场景 | 中小项目快速部署 | 大型项目独立优化 |
| 安全性 | 后端隐藏内网 | 后端暴露公网,建议 Nginx 防护 |
location /api/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
add_header Access-Control-Allow-Credentials true;
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_servers;
}| 响应头 | 作用 |
|---|---|
Access-Control-Allow-Origin | 允许哪些域名访问(* 表示全部) |
Access-Control-Allow-Methods | 允许哪些 HTTP 方法 |
Access-Control-Allow-Headers | 允许哪些请求头 |
Access-Control-Allow-Credentials | 是否允许携带 Cookie |
生产环境建议将
*替换为具体域名以增强安全性。
CSRF 与跨域的关系
CSRF(跨站请求伪造)利用浏览器自动携带 Cookie 的特性,伪装用户发请求。同源策略防不了 CSRF——因为它限制的是读取响应,不是发送请求。有效防御:服务端生成 CSRF token,请求时校验。
// CSRF 攻击示例:恶意网站用 img 标签向银行发转账请求
// 浏览器自动带上银行网站的 cookie,等同以用户身份操作
var img = new Image();
img.src = "https://www.mybank.com/transfer?acc=badguy&amount=10000";CPU 亲和
将 Nginx 的 worker 进程固定绑定到特定 CPU 核心,避免进程在多个 CPU 之间频繁切换。
好处:
- 减少进程切换开销
- 高效利用 CPU 缓存(L1/L2 缓存数据始终有效)
- 降低内存访问延迟(绑定到同一 NUMA 节点)
坏处: 运行计算密集型任务时,某个 CPU 会被持续占用,其他 worker 可能长时间得不到 CPU,整体效率反而下降。
worker_processes auto;
worker_cpu_affinity auto; # 自动绑定(Nginx 1.9.10+)
# 手动绑定示例(4 核 CPU)
# worker_processes 4;
# worker_cpu_affinity 0001 0010 0100 1000;
# worker1→CPU0, worker2→CPU1, worker3→CPU2, worker4→CPU3适用场景:高并发 Web 服务。不适用:计算密集型任务。
相关页面
- Nginx Part1 资料摘要 — 安装/IO模型/优化参数/日志
- Nginx Part2 资料摘要 — TCP队列/reuseport/虚拟主机/Location匹配
- Nginx Part3 资料摘要 — return/代理/健康检查/负载均衡算法
- Nginx Part4 资料摘要 — 动静分离三大方案 / Rewrite / 其他模块
- Nginx Part5 资料摘要 — 架构优化三步法 / 系统优化 / 防盗链 / 跨域 / CPU亲和
- 跨域问题及 Cookie/Session/JWT — 同源策略 / CORS / CSRF/XSS / 会话保持
- SSL/TLS 及全站 HTTPS — HTTPS 配置 / 全站加密 / 证书获取
- SSL/TLS 与 HTTPS 加密体系 — 加密原理 / 证书体系 / 认证流程
- Nginx 优化 — 系统优化/代理长连接/缓存机制/防盗链/跨域/PHP优化(优化系列)
- Java Web 部署 — Java 部署与 Nginx 代理 Tomcat
- Shell 编程 6:Nginx systemd 服务单元制作
- 集群部署:Nginx 反向代理部署
- 负载均衡入门:Nginx stream 四层代理
- Haproxy:与 Nginx 对比、四层透传 Proxy Protocol
- CDN 层:Nginx + CDN 回源配置
- CDN 层(下):OpenResty(Nginx + LuaJIT)
- iptables/Netfilter
- LVS
- HTTP 协议
- Igor Sysoev — Nginx 创始人
- OpenResty — Nginx + LuaJIT 可编程网关