大家好!今天我们来聊点实在的,不讲虚的理论,只谈能让你 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_processes 和 worker_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 的使用。 -
buffer和flush:buffer=32k表示设置一个 32k 的缓冲区,flush=5s表示每 5 秒钟或者缓冲区满时将日志写入文件。这是一个在实时性和性能之间的权衡。
案例:一个广告系统的点击统计接口,QPS 高达数万次。如果每次请求都记录 access_log,磁盘 I/O 将会不堪重负。通过关闭这个 location 的 access_log,或者使用带缓冲的日志记录,可以大大缓解系统压力。
9. 开启 sendfile 和 tcp_nopush
这两个指令通常组合使用,用于优化 Nginx 处理静态文件的方式。
代码示例
http {
# 开启高效文件传输模式
sendfile on;
# 防止网络阻塞,必须在 sendfile 开启时才有效
tcp_nopush on;
}
解析与案例
-
sendfile on: 允许 Nginx 使用sendfile()系统调用来发送文件。数据直接在内核空间从磁盘文件描述符拷贝到套接字描述符,避免了数据在内核空间和用户空间之间的两次拷贝,效率极高。 -
tcp_nopush on: 这个指令告诉 Nginx 在一个数据包中发送尽可能多的数据,而不是立即发送小数据包,这有助于减少网络拥塞。
案例:一个软件下载站,提供各种大小文件的下载服务。开启 sendfile 和 tcp_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 服务器!