Nginx 性能飙升!10个拿来就用的实用技巧


大家好!今天我们来聊点实在的,不讲虚的理论,只谈能让你 Nginx 服务器性能飙升的实用技巧。无论你是刚接触 Nginx 的新手,还是经验丰富的老鸟,相信这些技巧都能给你带来一些启发。

Nginx 以其高性能和稳定性著称,但默认配置往往是“通用型”的,就像一件均码的衣服,不一定适合所有人。 为了榨干服务器的最后一滴性能,我们需要根据自己的业务场景进行“量身定制”。下面,我们就来看看这10个立竿见影的性能优化技巧。

1. 合理配置 Worker 进程数和连接数

这是 Nginx 性能优化的基础,也是最核心的配置。

  • worker_processes: 这个指令决定了 Nginx 要启动多少个工作进程来处理请求。怎么设置最合理呢?答案是:通常设置为等于你服务器的 CPU 核心数。 这样可以充分利用多核 CPU 的优势,避免 CPU 核心在不同进程间频繁切换带来的性能损耗。

  • worker_connections: 这个指令定义了每个 worker_process 能同时处理的最大连接数。 这个值不是越大越好,需要根据你的服务器内存和业务并发量来综合考虑。

代码示例

你可以通过 grep processor /proc/cpuinfo | wc -l 命令查看你的 CPU 核心数。 假设你有 4 个核心:

# nginx.conf

# 根据 CPU 核心数设置,或者直接设置为 auto
worker_processes 4;

events {
    # 每个 worker 进程的最大连接数
    worker_connections 1024;
}

解析与案例

worker_processesworker_connections 两个值的乘积,就是 Nginx 理论上能处理的最大并发连接数。但要注意,这个连接数包含了与客户端的连接以及与后端服务器的连接。

案例:一个高并发的静态资源服务器,拥有 8 核 CPU 和 16G 内存。我们可以将 worker_processes 设置为 8。对于 worker_connections,我们可以根据系统的最大文件句柄数(通过 ulimit -n 查看)来设置一个较高的值,比如 65535。这样配置可以确保 Nginx 有足够的能力来应对海量的并发请求。

2. 开启 Gzip 压缩,为你的网站“减负”

Gzip 压缩是一个性价比极高的优化手段。它可以在 Nginx 将响应发送给客户端之前,对其进行压缩,从而显著减少网络传输的数据量。 这意味着更快的页面加载速度和更少的带宽消耗。

代码示例

http 配置块中加入以下配置:

# nginx.conf

http {
    # 开启 Gzip
    gzip on;

    # 只有大于 1k 的文件才进行压缩
    gzip_min_length 1k;

    # 压缩级别,1-9,级别越高压缩率越高,但越消耗 CPU
    gzip_comp_level 6;

    # 需要进行 Gzip 压缩的文件类型
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;

    # 让代理服务器也能缓存 Gzip 压缩后的文件
    gzip_vary on;

    # 禁用对 IE6 及以下版本的 Gzip 压缩
    gzip_disable "MSIE [1-6]\.";
}

解析与案例

  • gzip_comp_level:压缩级别需要一个权衡。级别太高会增加服务器的 CPU 负担,太低则压缩效果不明显。通常设置为 4 到 6 是一个不错的选择。
  • gzip_types:只对特定类型的文件进行压缩,比如文本、CSS、JS 文件。图片、视频这类文件本身已经高度压缩,再次压缩意义不大,反而浪费 CPU 资源。

案例:一个内容门户网站,页面包含大量的 CSS 和 JavaScript 文件。开启 Gzip 压缩后,这些静态资源的大小可以减少 60%-80%,使得用户首次访问时的白屏时间大大缩短,用户体验得到明显提升。你可以通过浏览器开发者工具的 “Network” 面板,查看响应头中的 Content-Encoding: gzip 来确认压缩是否生效。

3. 开启 HTTP/2,让传输更高效

相比于 HTTP/1.1,HTTP/2 带来了多路复用、头部压缩、服务器推送等一系列新特性,可以极大地提升页面加载速度,尤其是在资源文件较多的情况下。

代码示例

server 配置块的 listen 指令后加上 http2 即可,非常简单。当然,前提是你的 Nginx 需要支持并开启 SSL/TLS。

# nginx.conf

server {
    # 监听 443 端口,开启 SSL 和 HTTP/2
    listen 443 ssl http2;

    server_name yourdomain.com;

    # SSL 证书配置
    ssl_certificate /path/to/your/fullchain.pem;
    ssl_certificate_key /path/to/your/privkey.pem;

    # ... 其他配置
}

解析与案例

HTTP/2 的多路复用特性允许浏览器在单个 TCP 连接上同时发起多个请求,解决了 HTTP/1.1 的队头阻塞问题,这对于现代网站中普遍存在的大量小图标、CSS 和 JS 文件请求的场景,优化效果尤其明显。

案例:一个图片分享网站,首页需要加载数十张缩略图。在 HTTP/1.1 下,浏览器需要建立多个 TCP 连接来并行下载图片,耗时较长。切换到 HTTP/2 后,所有图片都可以在一个连接上并发传输,加载速度得到飞跃性提升。

4. 善用缓存,减轻后端压力

缓存是提升性能最有效的手段之一。 Nginx 提供了强大的缓存功能,可以将静态文件甚至动态请求的响应缓存起来。 当下一个相同的请求到来时,Nginx 可以直接从缓存中返回结果,而无需请求后端服务。

代码示例

浏览器缓存(针对静态文件)

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    # 设置缓存过期时间为 30 天
    expires 30d;
    add_header Cache-Control "public";
}

代理缓存(针对动态内容)

# 在 http 块中定义缓存路径和参数
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

server {
    # ...
    location / {
        # 启用名为 my_cache 的缓存
        proxy_cache my_cache;
        proxy_pass http://my_backend;
        
        # 为 200 状态码的响应缓存 10 分钟
        proxy_cache_valid 200 10m;
    }
}

解析与案例

  • expires:让浏览器缓存静态资源,用户在后续访问时可以直接从本地读取,速度最快。
  • proxy_cache:在 Nginx 服务端缓存动态内容。这对于那些内容更新不频繁但计算量大的动态页面非常有效,可以极大地降低后端服务器的负载。

案例:一个电商网站的商品详情页。商品信息在一段时间内是固定的,但每次生成页面都需要查询数据库。通过配置 proxy_cache,将详情页缓存 5 分钟。在这 5 分钟内,成千上万的用户访问都可以直接由 Nginx 缓存响应,后端数据库的压力瞬间降到最低。

5. 优化 Keep-Alive 连接

Keep-Alive(长连接)可以复用 TCP 连接,避免了每个 HTTP 请求都经历“三次握手”和“四次挥手”的开销,对于降低延迟和节省服务器资源至关重要。

代码示例

http {
    # 设置客户端连接的 keep-alive 超时时间
    keepalive_timeout 65s;

    # 单个 keep-alive 连接上允许的最大请求数
    keepalive_requests 100;
}

解析与案例

  • keepalive_timeout: 设置一个合理的超时时间。时间太长会占用过多连接资源,导致新用户无法建立连接;时间太短则失去了长连接的意义。默认 75s,通常设置在 60s 左右是个不错的选择。
  • keepalive_requests: 限制一个长连接能处理的请求数,达到后会强制关闭连接,有助于防止内存泄漏。

案例:在一个 API 服务中,客户端会频繁地调用多个不同的接口。开启并合理配置 Keep-Alive 后,客户端可以在一个 TCP 连接上完成所有 API 调用,显著减少了网络延迟,提升了整体的响应性能。

6. 调整缓冲区(Buffers)大小

Nginx 在处理客户端请求和后端响应时会使用缓冲区。 合理配置缓冲区大小可以有效减少磁盘 I/O 操作,提升性能。

代码示例

http {
    # 客户端请求体缓冲区大小
    client_body_buffer_size 128k;
    
    # 客户端请求头缓冲区大小
    client_header_buffer_size 1k;

    # 设置代理缓冲区的数量和大小
    proxy_buffers 8 16k;

    # 代理响应头的缓冲区大小
    proxy_buffer_size 4k;
}

解析与案例

  • client_body_buffer_size:如果你的应用经常处理大的 POST 请求(如文件上传),适当调大这个值可以避免 Nginx 将请求体写入临时文件,从而减少磁盘 I/O。
  • proxy_buffers:当 Nginx 作为反向代理时,它会缓冲来自后端服务器的响应。如果响应较大,调大这个值可以避免将响应写入磁盘,直接在内存中处理,速度更快。

案例:一个支持文件上传的网站,默认的 client_body_buffer_size 较小,导致用户上传稍大一点的文件时,Nginx 就会频繁读写磁盘,造成服务器 I/O 压力增大,上传速度变慢。将此值调整到一个合理的大小(如 1M)后,性能得到显著改善。

7. 优化 SSL/TLS 性能

对于启用 HTTPS 的网站来说,SSL/TLS 握手会带来额外的性能开销。通过一些优化可以减少这部分开销。

代码示例

server {
    listen 443 ssl http2;
    # ...

    # 开启 SSL Session 缓存,1M 内存约可缓存 4000 个会话
    ssl_session_cache shared:SSL:10m;
    # Session 缓存超时时间
    ssl_session_timeout 10m;

    # 优先使用服务器端的加密套件
    ssl_prefer_server_ciphers on;
    # 定义高性能的加密套件
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
}

解析与案例

  • ssl_session_cache: 启用会话缓存后,客户端在短时间内再次连接时,可以复用之前的会话信息,跳过复杂的握手过程,大大加快连接建立速度。 1MB 的共享内存大约可以存储 4000 个会话。
  • ssl_ciphers: 选择更现代、性能更好的加密算法(如 AES-GCM),避免使用老旧且耗费性能的算法。

案例:一个移动 App 的后端 API,客户端会频繁与服务器进行短连接通信。开启 ssl_session_cache 后,每次通信的延迟降低了 30-50ms,显著提升了 App 的响应速度和用户体验。

8. 日志管理优化

日志记录对于问题排查和数据分析至关重要,但频繁的磁盘写入也会成为性能瓶颈。

代码示例

关闭不必要的 access_log
对于一些高频访问且无需记录日志的资源(如图片、心跳检查),可以关闭访问日志。

location ~* \.(jpg|jpeg|png|gif|ico)$ {
    access_log off;
    # ...
}

使用缓冲日志
将日志先写入内存缓冲区,当缓冲区满时再统一写入磁盘文件,减少 I/O 次数。

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

解析与案例

  • access_log off: 对于负载极高的服务器,关闭不必要的日志可以有效降低磁盘 I/O 和 CPU 的使用。
  • bufferflush: buffer=32k 表示设置一个 32k 的缓冲区,flush=5s 表示每 5 秒钟或者缓冲区满时将日志写入文件。这是一个在实时性和性能之间的权衡。

案例:一个广告系统的点击统计接口,QPS 高达数万次。如果每次请求都记录 access_log,磁盘 I/O 将会不堪重负。通过关闭这个 location 的 access_log,或者使用带缓冲的日志记录,可以大大缓解系统压力。

9. 开启 sendfiletcp_nopush

这两个指令通常组合使用,用于优化 Nginx 处理静态文件的方式。

代码示例

http {
    # 开启高效文件传输模式
    sendfile on;

    # 防止网络阻塞,必须在 sendfile 开启时才有效
    tcp_nopush on;
}

解析与案例

  • sendfile on: 允许 Nginx 使用 sendfile() 系统调用来发送文件。数据直接在内核空间从磁盘文件描述符拷贝到套接字描述符,避免了数据在内核空间和用户空间之间的两次拷贝,效率极高。
  • tcp_nopush on: 这个指令告诉 Nginx 在一个数据包中发送尽可能多的数据,而不是立即发送小数据包,这有助于减少网络拥塞。

案例:一个软件下载站,提供各种大小文件的下载服务。开启 sendfiletcp_nopush 后,文件传输的效率和服务器的吞吐量都得到了显著提升,尤其是在处理大文件时效果更为明显。

10. 选择合适的负载均衡策略

当你的网站流量增长到单台服务器无法承受时,就需要使用 Nginx 作为负载均衡器。 Nginx 提供了多种负载均衡策略,选择合适的策略对后端服务的性能至关重要。

代码示例

upstream my_backend {
    # 默认:轮询 (Round Robin)
    # server backend1.example.com;
    # server backend2.example.com;

    # 权重 (Weight)
    # server backend1.example.com weight=3;
    # server backend2.example.com;

    # IP 哈希 (IP Hash)
    # ip_hash;
    # server backend1.example.com;
    # server backend2.example.com;

    # 最少连接 (Least Connections)
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}

server {
    location / {
        proxy_pass http://my_backend;
    }
}

解析与案例

  • 轮询 (Round Robin): 默认策略,按顺序将请求分配给后端服务器,简单公平。
  • 权重 (Weight): 适用于后端服务器性能不均的场景,性能好的服务器可以分配更高的权重,处理更多请求。
  • IP 哈希 (ip_hash): 将来自同一 IP 的请求固定分配给同一台后端服务器,可以解决 Session 共享问题。
  • 最少连接 (least_conn): 将请求分配给当前活动连接数最少的服务器,特别适合处理耗时较长的请求,能实现更好的负载均衡。

案例:一个在线聊天应用,客户端与服务器之间是长连接。如果使用轮询策略,可能会导致某些后端服务器连接数过多而另一些很空闲。这时采用 least_conn 策略,可以将新来的连接请求智能地分配到最空闲的服务器上,实现更优的资源分配。

总结

性能优化是一个持续的过程,没有一劳永逸的配置。今天我们分享的这10个技巧,是 Nginx 性能调优中最常用也最有效的方法。

最后,请记住最重要的一点:每次修改配置后,一定要进行测试! 使用 nginx -t 检查语法,然后通过压力测试工具(如 Apache Benchmark, JMeter)来验证你的优化是否真的带来了性能提升。

希望这篇文章能帮助你打造出性能更强劲的 Nginx 服务器!


  目录