
一、基础配置优化:压榨硬件性能
1.1 worker 进程配置
Nginx 启动后由一个 Master 进程管理一群 Worker 进程。Worker 进程才是真正处理请求的地方,Master 只负责管理。
# /etc/nginx/nginx.conf
# 全局块
user nginx;
worker_processes auto; # ✅ 自动匹配 CPU 核心数(推荐)
worker_cpu_affinity auto; # ✅ 将 worker 绑定到对应 CPU,减少上下文切换
worker_priority -5; # 提高调度优先级(负数越高优先)
worker_rlimit_nofile 65535; # 每个 worker 能打开的文件描述符数量
# 错误日志
error_log /var/log/nginx/error.log warn;
# PID 文件
pid /var/run/nginx.pid;
events {
worker_connections 10240; # 每个 worker 最大并发连接数
use epoll; # ✅ Linux 高效 I/O 事件模型(生产环境必须)
multi_accept on; # ✅ 一次接受多个新连接
}关键参数解读:
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
worker_processes |
1 | auto |
自动等于 CPU 核心数 |
worker_connections |
512 | 10240+ | 单进程最大并发数 |
worker_rlimit_nofile |
— | 65535 | 文件描述符上限,需配合系统 ulimit -n |
multi_accept |
off | on | 一次接收多个连接,减少 accept() 调用 |
use epoll |
— | epoll | Linux 下最高效的事件模型 |
系统层文件描述符限制:
# 查看当前限制
ulimit -n
# 临时生效(重启失效)
ulimit -n 100000
# 永久生效:编辑 /etc/security/limits.conf
nginx soft nofile 100000
nginx hard nofile 100000
# 编辑 /etc/sysctl.conf
echo "fs.file-max = 2097152" >> /etc/sysctl.conf
sysctl -p1.2 HTTP 连接与传输优化
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# ── 传输效率优化 ──────────────────────────────
sendfile on; # ✅ 启用零拷贝:文件从磁盘直发网络,不走用户态
tcp_nopush on; # ✅ sendfile 开启时:等凑满一个数据包再发,减少小包数量
tcp_nodelay on; # ✅ 禁用 Nagle 算法,小数据包立即发送(适合实时响应)
aio on; # ✅ 异步 I/O,配合 directio 使用(大文件场景)
directio 512; # 超过 512KB 的文件用 directio 跳过系统缓存(Linux)
open_file_cache max=10000 inactive=60s; # 缓存文件元数据,减少 stat() 系统调用
open_file_cache_valid 30s; # 元数据缓存有效期
open_file_cache_min_use 5; # 访问 5 次后才缓存
# ── 连接超时优化 ──────────────────────────────
keepalive_timeout 65; # 客户端保持连接时长(65秒)
keepalive_requests 10000; # 单连接最大请求数,防止长连接滥用
client_header_timeout 10s; # 读取请求头超时
client_body_timeout 10s; # 读取请求体超时
send_timeout 10s; # 发送给客户端超时
reset_timedout_connection on; # 连接关闭时立即释放内存
# ── 请求体与请求头限制 ──────────────────────────
client_max_body_size 50m; # 最大请求体(上传文件)
client_header_buffer_size 4k; # 请求头缓冲区
large_client_header_buffers 4 32k; # 大请求头(JWT/长 Cookie 场景)
}零拷贝原理说明:
传统模式(sendfile off):
磁盘 → 内核缓冲区 → 用户缓冲区 → Socket缓冲区 → 网卡
(4 次数据拷贝 + 2 次上下文切换)
零拷贝模式(sendfile on):
磁盘 → 内核缓冲区 → Socket缓冲区 → 网卡
(2 次数据拷贝 + 0 次上下文切换)二、Gzip 压缩:减少 60%-80% 传输量
2.1 Gzip 基础配置
http {
gzip on; # ✅ 启用 Gzip 压缩
gzip_vary on; # ✅ 根据 Accept-Encoding 缓存不同版本
gzip_proxied any; # 代理请求也压缩(即使后端已压缩)
gzip_disable "msie6"; # IE6 不支持,禁用
# 压缩级别(1-9,默认 4)
# 级别越高压缩率越高,但 CPU 开销越大
# CDN/中转节点:4-5;自有服务器:5-6;静态资源密集型:6
gzip_comp_level 5;
# 最小压缩阈值:小于此大小的文件不压缩(避免浪费 CPU)
gzip_min_length 1024;
# ✅ 压缩的文件 MIME 类型
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
application/xml+rss
application/x-javascript
application/x-font-ttf
application/x-web-app-manifest+json
font/opentype
font/ttf
font/eot
font/otf
image/svg+xml
image/x-icon;
}2.2 Gzip 压缩效果实测
# 未压缩时的响应
curl -I -H "Accept-Encoding: gzip" https://example.com/api/data.json
# Content-Length: 524288 (512KB)
# 启用 Gzip 后(压缩率约 5)
curl -I -H "Accept-Encoding: gzip" https://example.com/api/data.json
# Content-Length: 81920 (80KB)
# 节省约 84% 带宽2.3 Brotli 压缩(更优选择)
Brotli 是 Google 推出的新一代压缩算法,同等压缩级别下比 Gzip 小 15%-25%:
http {
# 需要安装 nginx-module-brotli
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
brotli on;
brotli_comp_level 6; # Brotli 压缩级别(1-11)
brotli_types
text/plain
text/css
application/javascript
application/json
application/xml
image/svg+xml
font/ttf
font/otf
font/eot;
}三、缓存策略:让静态资源"永不过期"
3.1 浏览器缓存配置
server {
listen 80;
server_name example.com;
root /var/www/html;
# ── 静态资源缓存(永不过期 + 版本化)──────────────
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y; # 缓存 1 年
add_header Cache-Control "public, immutable"; # immutable:URL 不变则永不变
add_header X-Cache-Status $upstream_cache_status; # HIT/MISS 调试用
access_log off; # 静态资源关闭日志,省 I/O
}
# ── HTML 文件(始终经过后端,确保最新)────────────
location ~* \.html$ {
expires -1; # 不缓存,每次请求最新
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}3.2 代理缓存(反向代理缓存)
http {
# ── 代理缓存配置 ──────────────────────────────
proxy_cache_path /var/cache/nginx levels=1:2
keys_zone=api_cache:100m
max_size=10g
inactive=60m
use_temp_path=off;
# ── API 缓存策略 ─────────────────────────────
upstream backend {
server 127.0.0.1:8080;
keepalive 32; # 与后端保持长连接,减少建连开销
}
server {
listen 80;
server_name api.example.com;
# ✅ 缓存 GET/HEAD 请求(POST/PUT 等写操作不缓存)
proxy_cache_lock on; # 防止缓存击穿
proxy_cache_lock_timeout 5s;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_background_update on; # 后台更新缓存,用户无感知
proxy_cache_valid 200 60s; # 200 响应缓存 60 秒
proxy_cache_valid 404 1m; # 404 缓存 1 分钟
proxy_cache_key "$scheme$request_method$host$request_uri$http_x_custom"; # 含自定义 header 区分用户
add_header X-Cache-Status $upstream_cache_status;
location /api/ {
proxy_pass http://backend;
proxy_cache api_cache;
# 缓存清理:缓存失效时立即回源,不等 inactive 时间
proxy_cache_purge PURGE from 127.0.0.1;
}
}
}3.3 FastCGI 缓存(PHP 应用)
http {
# FastCGI 缓存配置
fastcgi_cache_path /var/cache/nginx/fcgi levels=1:2
keys_zone=fcgi_cache:100m
max_size=5g
inactive=2h;
server {
listen 80;
server_name www.example.com;
# 绕过缓存的条件
set $skip_cache 0;
if ($request_uri ~* "/admin|/login|/cart") {
set $skip_cache 1; # 管理后台/登录/购物车不缓存
}
if ($http_cookie ~* "wordpress_logged_in") {
set $skip_cache 1; # 登录用户不缓存
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 缓存控制
fastcgi_cache fcgi_cache;
fastcgi_cache_valid 200 10m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 5s;
add_header X-FastCGI-Cache $upstream_cache_status;
}
}
}四、负载均衡与高可用
4.1 常用负载均衡策略
upstream backend_servers {
# ── 轮询(默认):每台机器轮流处理 ───────────
# server 10.0.0.11:8080;
# server 10.0.0.12:8080;
# server 10.0.0.13:8080 down; # down 表示永久剔除
# ── 加权轮询:权重越高,分到的请求越多 ─────────
server 10.0.0.11:8080 weight=5;
server 10.0.0.12:8080 weight=3;
server 10.0.0.13:8080 weight=2 backup; # backup:仅所有非 backup 节点 down 时启用
# ── IP 哈希:同一 IP 始终路由到同一后端(适合有状态的场景)
# ip_hash;
# ── 最少连接:优先分配给连接数最少的节点 ───────
least_conn;
# 长连接复用:减少与后端的建连次数
keepalive 32;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_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;
# 健康检查
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_502 http_503; # 失败自动切到下一台
}
}4.2 健康检查配置
upstream backend {
server 10.0.0.11:8080 max_fails=3 fail_timeout=30s; # 30秒内失败3次则摘除
server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
}五、安全防护配置
5.1 隐藏版本号与敏感信息
server {
server_tokens off; # ✅ 关闭 Server 头显示 Nginx 版本号
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# 自定义 Server 头(迷惑扫描器)
add_header Server "Apache/2.4.41" always;
}5.2 防盗链配置
server {
server_name example.com;
# 允许访问的域名白名单
valid_referers none blocked ~\.google\. ~\.baidu\. example.com *.example.com;
if ($invalid_referer) {
return 403;
# 或者重定向到一张警告图片
# rewrite ^/.*$ /static/hotlink.jpg break;
}
location /uploads/ {
valid_referers ~\.google\. ~\.baidu\. example.com;
if ($invalid_referer) {
return 403;
}
}
}5.3 限流防护
http {
# ── 连接数限制 ───────────────────────────────
# 基于 IP 的并发连接数限制
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# ── 请求速率限制 ───────────────────────────────
# 每个 IP 每秒最多 10 个请求(令牌桶算法)
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
server {
listen 80;
server_name example.com;
# 连接数限制:每个 IP 同时最多 5 个连接
limit_conn conn_limit 5;
# 请求速率限制:突发最多 20 个请求,超出的返回 503
limit_req zone=req_limit burst=20 nodelay;
# 返回 429 代替默认的 503(更友好的限流提示)
limit_req_status 429;
limit_conn_status 429;
# 限制单个 IP 同时下载速度(bytes/s)
limit_rate_after 1m; # 前 1MB 不限速
limit_rate 200k; # 之后限速 200KB/s
}
}5.4 防爬虫与恶意请求
server {
listen 80;
server_name example.com;
# ── UA 黑名单 ───────────────────────────────
if ($http_user_agent ~* "(AhrefsBot|SemrushBot|MJ12bot|scrapbot|Python-urllib)") {
return 403;
}
# ── 禁止通过代理访问 ───────────────────────
if ($http_via ~* ".+") {
return 403;
}
# ── 常见攻击路径拦截 ───────────────────────
location ~ /\.(git|svn|hg|env|config|bak)$ {
deny all;
access_log off;
log_not_found off;
}
# SQL 注入防护
if ($query_string ~* "union.*select.*\(") {
return 403;
}
# XSS 防护
if ($query_string ~* "<.*>") {
return 403;
}
}六、HTTPS 与 HTTP/2 优化
6.1 SSL/TLS 配置
server {
listen 443 ssl http2; # ✅ HTTP/2 配合 HTTPS 使用
server_name example.com;
# ── SSL 证书配置 ────────────────────────────
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# ── TLS 版本控制(禁用老旧协议)───────────────
ssl_protocols TLSv1.2 TLSv1.3; # ✅ 只启用 TLS 1.2 和 1.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:50m; # 50MB 缓存,减少握手开销
ssl_session_timeout 1d; # 缓存有效期 1 天
ssl_session_tickets on; # 支持会话票据(无状态恢复)
# ── OCSP Stapling(减少证书验证延迟)──────────
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}6.2 HTTP/2 与多路复用
# HTTP/2 的核心优势:
# 1. 多路复用:一个连接并行处理多个请求(无需排队)
# 2. Header 压缩(HPACK):减少头部冗余
# 3. 服务端推送:主动推送 CSS/JS 等资源
# 4. 流量控制:按优先级分配带宽
server {
listen 443 ssl http2;
server_name example.com;
# 服务端推送示例(推送关键 CSS/JS)
location = /index.html {
http2_push /static/css/main.css;
http2_push /static/js/app.js;
http2_push /static/fonts/icon.woff2;
}
}七、压测与监控:用数据验证优化效果
7.1 压测工具:wrk
# 安装 wrk(Linux/macOS)
# Ubuntu: apt install wrk
# macOS: brew install wrk
# ── 基础压测:静态文件 ─────────────────────────
wrk -t12 -c400 -d30s http://127.0.0.1/index.html
# -t12 : 12 个线程
# -c400: 400 个并发连接
# -d30s: 持续 30 秒
# 输出示例:
# Running 30s test @ http://127.0.0.1/index.html
# Thread Stats Avg Stdev Max +/- Stdev
# Latency 12.34ms 5.67ms 89.23ms 85.32%
# Req/Sec 3205.56 234.12 4200.00 68.21%
# 356234 requests in 30.01s, 4.28GB read
# Socket errors: connect 0, read 0, write 0, timeout 0
# Requests/sec: 11872.34 ← 关键指标:QPS
# Transfer/sec: 146.12MB
# ── 带 Lua 脚本的压测:模拟真实用户行为 ─────────
# post.lua:每个请求带上随机用户 ID
wrk -t8 -c200 -d60s -s post.lua http://127.0.0.1/api/userspost.lua 示例:
-- post.lua:POST 请求压测脚本
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body = '{"username":"user123","action":"login"}'7.2 Nginx 内置状态监控
http {
# 启用 status 监控模块
server {
listen 80;
server_name localhost;
location /nginx_status {
stub_status on; # ✅ 开启状态监控
access_log off;
allow 127.0.0.1; # 仅本地访问
deny all;
}
}
}# 查看状态
curl http://127.0.0.1/nginx_status
# Active connections: 291 ← 当前活跃连接数
# server accepts handled requests
# 16630948 16630948 31070465 ← 总接受数 / 总连接数 / 总请求数
# Reading: 6 Writing: 179 Waiting: 106 ← 读/写/等待状态7.3 优化前后对比(实测数据参考)
以 4 核 CPU / 8GB 内存服务器,100KB 静态资源为例:
| 优化项 | 优化前 QPS | 优化后 QPS | 提升幅度 |
|---|---|---|---|
| 默认配置 | ~3,200 | — | 基准 |
| + worker_processes auto + epoll | — | ~9,800 | +206% |
| + sendfile + tcp_nopush + tcp_nodelay | — | ~14,500 | +48% |
| + gzip 压缩(text/css/js) | — | ~28,000 | +93% |
| + open_file_cache + expires 缓存 | — | ~45,000 | +61% |
| 全部优化 + CDN 接入 | — | ~120,000+ | +167% |
八、生产环境完整配置模板
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_priority -5;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 10240;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 传输优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
aio on;
directio 512;
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 30s;
# 连接与超时
keepalive_timeout 65;
keepalive_requests 10000;
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;
reset_timedout_connection on;
# 请求限制
client_max_body_size 50m;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml font/ttf font/woff;
# 安全头
server_tokens off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# 限流
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# ── 上游服务器 ──────────────────────────────
upstream backend {
least_conn;
server 127.0.0.1:8080 weight=3;
server 127.0.0.1:8081 weight=2;
server 127.0.0.1:8082 weight=1 backup;
keepalive 32;
}
# ── 静态资源服务器 ───────────────────────────
server {
listen 80;
server_name static.example.com;
root /var/www/static;
index index.html;
# 静态资源永缓存
location ~* \.(css|js|jpg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
gzip_static on; # 优先使用预压缩文件
}
# HTML 不缓存
location ~* \.html$ {
expires -1;
}
}
# ── API 反向代理 ────────────────────────────
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend;
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_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
# 限流
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 5;
}
# 健康检查接口
location /health {
access_log off;
return 200 "OK";
}
}
}结语
Nginx 的性能优化是一个系统性工程,核心在于三点:减少 I/O(零拷贝、缓存、压缩)、减少连接开销(长连接复用、worker 优化)、精准控制流量(限流、安全头、防盗链)。建议按以下路径推进:
第一步:检查当前 QPS 基线(wrk 压测)
第二步:按本文配置逐项优化,每次改完压测一次
第三步:观察 Nginx status 和慢查询日志,确认优化生效
第四步:接入 Prometheus + Grafana 持续监控,长期保持最优状态
评论
暂无评论
评论(0)