跳到主要内容

性能优化

本章将介绍 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 测试性能

延伸阅读