Nginx 性能优化:提升网站速度的技巧

通过我们全面的性能优化指南,释放您的 Nginx 服务器的全部潜力。学习如何微调工作进程、实施强大的缓存策略、启用高效压缩(Gzip/Brotli)以及优化连接处理。本文提供了实用的 Nginx 配置技巧和最佳实践,以大幅减少加载时间、改善用户体验,并提升您网站的整体速度和效率。对于寻求巅峰性能的系统管理员和 Web 开发人员来说,这是必读内容。

Nginx性能优化:打造更快网站的实用技巧

网站速度慢通常源于几个原因:昂贵的上游响应、缺少缓存头、资源过大、工作进程阻塞,或者服务器配置仅采用默认值而非针对流量优化。Nginx性能优化最佳实践是:先测量,一次只改一个设置,并保持配置清晰可读。

以下示例可作为起点,然后针对你自己的应用进行负载测试。静态文件服务器、WordPress/PHP-FPM站点和API反向代理需要不同的权衡策略。

理解Nginx性能瓶颈

首先找到瓶颈。常见原因包括:

  • CPU使用率: 高CPU负载会拖慢请求处理、压缩和TLS工作。
  • 内存压力: 交换会严重损害延迟。
  • 网络I/O: 慢速链路、小的上游窗口或丢包可能主导响应时间。
  • 磁盘I/O: 静态文件、缓存文件和日志仍会触及存储。
  • 上游延迟: Nginx可能很快,但你的应用服务器可能很慢。

tophtopiostatss、访问日志和Nginx的stub_status模块等工具可以帮助你决定调整什么。

核心Nginx优化技术

工作进程和连接数

worker_processes指令控制Nginx启动的工作进程数量。auto是一个实用的默认值,因为Nginx会检测可用的CPU核心。

# 将worker_processes设置为CPU核心数
worker_processes auto;

在每个工作进程内,worker_connections限制该工作进程可以打开的同时连接数。粗略上限是worker_processes * worker_connections,但实际容量还取决于上游连接、打开文件限制、keep-alive行为和操作系统限制。

# 为高流量站点增加worker_connections
worker_connections 1024;

如果看到Too many open files,仅提高worker_connections是不够的。还需要检查服务的文件描述符限制,通常由systemd的LimitNOFILE或shell限制控制。

缓存策略

缓存通常是影响最大的Nginx性能优化,因为它可以避免重复工作。

浏览器缓存

告诉浏览器缓存版本化的静态资源,如图片、CSS和JavaScript。仅在部署时文件名发生变化(如app.8f3c1.css)的情况下使用长缓存时间。

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public";
}

代理缓存

如果Nginx是反向代理,它可以缓存选定的后端响应。这适用于公共页面、具有明确新鲜度规则的API响应以及不因用户而变化的昂贵页面。

首先,在http块中定义缓存区域:

http {
    # ... 其他http配置 ...
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
    # ...
}
  • /var/cache/nginx:缓存文件存储的目录。
  • levels=1:2:定义缓存的目录结构。
  • keys_zone=my_cache:10m:创建一个名为my_cache的共享内存区域,大小为10MB,用于存储缓存键。
  • max_size=1g:设置缓存的最大大小。
  • inactive=60m:移除60分钟内未被访问的缓存条目。

然后,在location块中启用缓存:

location / {
    proxy_pass http://your_backend_app;
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m; # 缓存200和302响应10分钟
    proxy_cache_valid 404 1m;     # 缓存404响应1分钟
    add_header X-Cache-Status $upstream_cache_status;
}

add_header X-Cache-Status $upstream_cache_status; 对调试很有用,可以显示请求是缓存命中、未命中还是绕过。

不要缓存个性化页面,除非你的缓存键考虑了改变响应的数据。例如,登录后的仪表板通常应绕过代理缓存,而/assets/logo.png可以长时间缓存。

压缩

压缩可以减少基于文本的响应(如HTML、CSS、JavaScript、JSON和XML)的传输大小。对于已经压缩的文件(如JPEG、PNG、MP4或许多归档格式),压缩帮助不大。

http {
    # ...
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    # ...
}
  • gzip on;:启用Gzip压缩。
  • gzip_vary on;:添加Vary: Accept-Encoding头,这对缓存代理很重要。
  • gzip_proxied any;:也对代理请求的响应进行压缩。
  • gzip_comp_level 6;:设置压缩级别(1-9,越高压缩越好但CPU消耗越大)。
  • gzip_types ...;:指定要压缩的MIME类型。

Brotli可以很好地压缩文本资源,但标准的开源Nginx构建并不都支持Brotli。在添加Brotli指令之前,请检查你的软件包或模块集。

连接处理和Keep-Alive

keepalive_timeout指令控制空闲客户端连接保持打开的时间。重用连接可以避免额外的TCP和TLS握手,但空闲连接仍会消耗资源。

http {
    # ...
    keepalive_timeout 65;
    keepalive_requests 1000;
    # ...
}
  • keepalive_timeout 65;:将keep-alive超时设置为65秒。
  • keepalive_requests 1000;:设置单个keep-alive连接上可以处理的最大请求数。

对于有许多短请求的API,keep-alive很有帮助。对于有许多空闲客户端的小型服务器,较短的超时可能更好。

缓冲和请求大小限制

Nginx使用缓冲区来处理客户端请求体和代理响应。默认值对许多站点来说没问题,但上传密集型应用和大的上游头可能需要显式设置。

http {
    # ...
    client_body_buffer_size 10K;
    client_max_body_size 8M;
    proxy_buffers 8 16k;
    proxy_buffer_size 16k;
    proxy_connect_timeout 60;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    # ...
}
  • client_body_buffer_size:用于读取客户端请求体的缓冲区大小。
  • client_max_body_size:客户端请求体的最大允许大小。
  • proxy_buffersproxy_buffer_size:控制Nginx作为代理时的缓冲。

避免盲目复制缓冲区设置。如果看到upstream sent too big header,在提高proxy_buffer_size之前先调查上游头。如果上传失败并显示413 Request Entity Too Large,将client_max_body_size设置为你的应用实际支持的大小。

TLS优化

对于HTTPS站点,TLS设置会影响延迟和安全性。

  • 会话恢复: 使用会话缓存来加速重复连接。
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    
  • TLS版本: 除非兼容性要求另有规定,否则启用TLS 1.2和TLS 1.3。
  • OCSP装订: 当证书链支持时,可以减少证书验证的往返次数。
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    

静态文件服务

Nginx擅长提供静态文件。这些指令在http块中很常见:

  • sendfile 允许内核在支持的系统上直接将文件数据复制到套接字。
    sendfile on;
    
  • tcp_nopushtcp_nodelay 针对常见HTTP工作负载调整数据包发送行为。
    tcp_nopush on;
    tcp_nodelay on;
    

监控和测试

每次更改后,进行测试和比较。有用的工具包括:

  • Nginx stub_status 活动连接、接受的连接、处理的连接和请求数。
  • top/htop CPU和内存压力。
  • iostat 磁盘I/O。
  • WebPageTest或PageSpeed Insights: 浏览器端性能。
  • wrkabhey 针对受控端点的本地负载测试。

保留先前配置的副本,运行sudo nginx -t,重新加载,然后比较延迟、错误率、CPU和上游响应时间。最好的Nginx性能优化是你的测量结果能够证明的优化。

实用要点

从测量开始,然后首先修复最大的瓶颈。对于大多数网站来说,这意味着设置合理的工作进程限制、为静态资源添加浏览器缓存、启用gzip、缓存安全的上游响应,并在每次重新加载后监控日志。