跳到主要内容

Nginx 性能调优

Worker 进程配置

nginx.conf 全局配置
# worker 数量 = CPU 核心数
worker_processes auto;

# 绑定 CPU 亲和性(减少上下文切换)
worker_cpu_affinity auto;

events {
# 每个 worker 的最大连接数
worker_connections 10240;

# Linux 下推荐 epoll
use epoll;

# 允许一次性接受所有新连接
multi_accept on;
}
提示

worker_connections × worker_processes = Nginx 可处理的最大并发连接数。作为反向代理时,每个客户端连接实际占用 2 个连接(客户端→Nginx + Nginx→后端)。

文件传输优化

http {
# sendfile: 内核态直接传输文件,避免用户态拷贝
sendfile on;

# 配合 sendfile,在一个 TCP 包中发送 HTTP 响应头和文件内容
tcp_nopush on;

# 小数据包立即发送(关闭 Nagle 算法)
tcp_nodelay on;

# 保持连接超时
keepalive_timeout 65;
keepalive_requests 1000;
}

Gzip 压缩

http {
gzip on;
gzip_min_length 1k; # 小于 1KB 不压缩
gzip_comp_level 4; # 压缩级别 1-9,推荐 4-6
gzip_types
text/plain
text/css
text/javascript
application/json
application/javascript
image/svg+xml;
gzip_vary on; # 添加 Vary: Accept-Encoding
gzip_static on; # 优先使用预压缩的 .gz 文件
}

代理缓存

http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:20m
max_size=2g inactive=60m use_temp_path=off;

server {
location /api/ {
proxy_pass http://backend;
proxy_cache app_cache;
proxy_cache_valid 200 10m; # 200 响应缓存 10 分钟
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
}
}

静态资源优化

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;

# 打开文件缓存(减少磁盘 IO)
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
}

关键性能参数速查

参数推荐值说明
worker_processesauto等于 CPU 核心数
worker_connections10240高并发场景可提高
keepalive_timeout65s长连接超时
gzip_comp_level4-6压缩率与 CPU 的平衡点
proxy_cache_valid按场景API 短缓存,静态资源长缓存

常见面试问题

Q1: Nginx 为什么能支撑高并发?

答案

  1. 事件驱动 + 异步非阻塞:基于 epoll,单个 worker 可处理数千并发连接
  2. 多 worker 进程:充分利用多核 CPU,worker 间无锁竞争
  3. 零拷贝:sendfile 内核态传输,避免用户态缓冲区拷贝
  4. 内存池:预分配内存块,减少 malloc/free 开销

Q2: sendfile、tcp_nopush、tcp_nodelay 三者的关系?

答案

  • sendfile:内核态直接发送文件,跳过用户态拷贝
  • tcp_nopush(配合 sendfile):将响应头和文件内容合并到尽可能少的 TCP 包中发送(Nagle 聚合)
  • tcp_nodelay:小数据包立即发送,不等待聚合

看似矛盾但实际协同:tcp_nopush 在发送大块文件时聚合,最后一个包时切换为 tcp_nodelay 立即发送,兼顾吞吐量和延迟。

相关链接