跳到主要内容

性能优化

本章将介绍 Nginx 性能优化的各种技巧,帮助你充分发挥 Nginx 的性能潜力。

系统级优化​

文件描述符限制​

Nginx 需要大量文件描述符处理并发连接:

# 查看当前限制
ulimit -n

# 临时修改
ulimit -n 65535

# 永久修改 - /etc/security/limits.conf
nginx soft nofile 65535
nginx hard nofile 65535

# Systemd 服务配置 - /etc/systemd/system/nginx.service
[Service]
LimitNOFILE=65535

内核参数优化​

# /etc/sysctl.conf

# TCP 连接优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_tw_buckets = 5000

# TCP 缓冲区
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# 文件描述符
fs.file-max = 2097152

# 应用配置
sysctl -p

Nginx 配置优化​

Worker 进程配置​

# 自动检测 CPU 核心数(推荐)
worker_processes auto;

# 绑定 CPU(可选,减少上下文切换)
worker_cpu_affinity auto;

# 每个 worker 的最大连接数
events {
worker_connections 65535;
worker_rlimit_nofile 65535;
}

解释:

  • worker_processes auto:自动使用所有 CPU 核心
  • worker_cpu_affinity:将 worker 进程绑定到特定 CPU
  • worker_connections:每个 worker 的最大连接数

事件模型​

events {
# 使用 epoll(Linux 最佳选择)
use epoll;

# 允许同时接受多个连接
multi_accept on;

# 每个 worker 最大连接数
worker_connections 65535;
}

事件模型选择:

  • epoll:Linux 2.6+,性能最佳
  • kqueue:FreeBSD、macOS
  • select:所有平台,性能最差
  • poll:大多数 Unix 系统

HTTP 优化​

连接优化​

http {
# 开启 sendfile(零拷贝)
sendfile on;

# 合并数据包发送
tcp_nopush on;
tcp_nodelay on;

# 保持连接
keepalive_timeout 65;
keepalive_requests 1000;

# 客户端超时
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
}

缓冲区优化​

http {
# 客户端请求体缓冲区
client_body_buffer_size 16k;
client_max_body_size 8m;

# 请求头缓冲区
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

# 输出缓冲区
output_buffers 2 32k;

# 预读取
aio on;
directio 512k;
}

Gzip 压缩​

http {
# 开启 gzip
gzip on;
gzip_vary on;
gzip_proxied any;

# 压缩级别(1-9,推荐 4-6)
gzip_comp_level 5;

# 最小压缩大小
gzip_min_length 256;

# 压缩的 MIME 类型
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/rss+xml
image/svg+xml;

# 缓冲区
gzip_buffers 16 8k;
}

解释:

  • gzip_comp_level:压缩级别越高,CPU 消耗越大
  • gzip_min_length:小文件压缩反而可能变大
  • gzip_vary:告诉代理存在压缩版本

静态文件优化​

缓存配置​

# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
root /var/www/static;

# 浏览器缓存
expires 1y;
add_header Cache-Control "public, immutable";

# 关闭访问日志
access_log off;

# 开启 sendfile
sendfile on;
tcp_nopush on;
}

文件元数据缓存​

http {
# 文件描述符缓存
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}

参数说明:

  • max:缓存的文件描述符数量
  • inactive:非活跃条目的过期时间
  • valid:检查缓存有效性的时间间隔
  • min_uses:访问次数达到多少才缓存

代理优化​

上游连接池​

upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;

# 保持长连接
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 60s;
}

server {
location / {
proxy_pass http://backend;

# 使用 HTTP/1.1 长连接
proxy_http_version 1.1;
proxy_set_header Connection "";

# 代理头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

代理缓冲​

location / {
proxy_pass http://backend;

# 开启代理缓冲
proxy_buffering on;

# 缓冲区配置
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;

# 临时文件
proxy_max_temp_file_size 256m;
proxy_temp_file_write_size 32k;
}

负载均衡优化​

upstream backend {
# 最少连接策略
least_conn;

# 长连接
keepalive 64;
keepalive_requests 10000;
keepalive_timeout 60s;

# 服务器配置
server 192.168.1.101:8080 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8080 backup;
}

缓存代理​

代理缓存配置​

# 定义缓存路径
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;
proxy_cache_key $scheme$host$request_uri;

# 缓存有效期
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 5m;

# 缓存锁(防止缓存击穿)
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;

# 使用过期缓存(当后端不可用时)
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;

# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;
}
}

缓存状态:

  • HIT:缓存命中
  • MISS:缓存未命中
  • EXPIRED:缓存过期
  • STALE:使用过期缓存
  • UPDATING:正在更新缓存

缓存清除​

# 清除缓存的方法
location /purge {
# 限制访问
allow 127.0.0.1;
deny all;

# 删除缓存文件
proxy_cache_purge my_cache $scheme$host$request_uri;
}

限流优化​

请求限流​

# 定义限流区域(基于 IP)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;

# 全局限流
limit_req zone=api_limit burst=200 nodelay;

# 特定接口限流
location /api/login {
limit_req zone=api_limit burst=5 nodelay;
}

连接数限制​

# 定义连接数限制区域
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# 限制每个 IP 的并发连接数
server {
limit_conn conn_limit 50;
limit_conn_status 429;
}

日志优化​

异步日志​

# 使用缓冲写入日志
access_log /var/log/nginx/access.log main buffer=64k flush=5s;

# 关闭不需要的日志
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
access_log off;
}

条件日志​

# 只记录错误请求
map $status $is_error {
~^[45] 1;
default 0;
}
access_log /var/log/nginx/error_requests.log combined if=$is_error;

监控和调试​

Stub Status​

server {
listen 8080;
server_name localhost;

location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
}

访问后显示:

Active connections: 291 
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106

性能测试​

# 使用 ab 测试
ab -n 10000 -c 100 http://example.com/

# 使用 wrk 测试
wrk -t12 -c400 -d30s http://example.com/

# 使用 hey 测试
hey -n 10000 -c 100 http://example.com/

完整优化配置​

user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
use epoll;
multi_accept on;
worker_connections 65535;
}

http {
include /etc/nginx/mime.types;
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" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log main buffer=64k flush=5s;

# 文件优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 连接优化
keepalive_timeout 65;
keepalive_requests 1000;
reset_timedout_connection on;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;

# 缓冲区
client_body_buffer_size 16k;
client_max_body_size 8m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
application/rss+xml image/svg+xml;

# 文件缓存
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

# 包含站点配置
include /etc/nginx/conf.d/*.conf;
}

小结​

本章学习了:

  1. 系统级优化(文件描述符、内核参数)
  2. Nginx 进程和事件优化
  3. HTTP 优化(连接、缓冲区、Gzip)
  4. 静态文件优化
  5. 代理和负载均衡优化
  6. 缓存配置
  7. 限流配置
  8. 日志优化
  9. 监控和性能测试

练习​

  1. 配置系统参数优化
  2. 配置 Gzip 压缩
  3. 配置静态文件缓存
  4. 配置代理缓存
  5. 使用 wrk 测试性能

延伸阅读​