Nginx 高性能配置实战:个人站长如何把网站访问速度提升一倍

前言:为什么你的网站加载这么慢

很多个人站长都有过这样的困惑:明明服务器带宽不小、配置也不差,可网站打开就是慢,尤其是第一次访问的时候,白屏好几秒。排查下来,问题往往不是出在服务器硬件上,而是出在 Nginx 的默认配置上。Nginx 默认配置追求的是"稳妥",而不是"性能",它不会自动帮你启用 gzip 压缩、不会帮你设置合理的缓存策略、也不会针对你的服务器 CPU 核数做并发调优。这篇文章就从个人站长的实际场景出发,分享一套经过实战验证的 Nginx 优化方案,全部配置都有注释,照着抄就能用。

一、先看你的服务器有几核 CPU

Nginx 优化第一步,是让 worker 进程数量匹配 CPU 核心数。worker_processes 决定 Nginx 启动多少个工作进程,设置太多会白白消耗内存,设置太少则无法充分利用多核 CPU。先执行 nproc 查看核心数,然后在 nginx.conf 中设置:

worker_processes auto;  # 或者直接写数字,比如 4

同时建议开启 worker 进程的 CPU 亲和性,让每个进程绑定到固定的 CPU 核心上,减少进程切换带来的开销:

worker_cpu_affinity auto;

还有一个容易被忽略的参数是 worker_rlimit_nofile,它限制每个 worker 进程能打开的文件描述符数量。默认值往往只有 1024,对于并发稍高的站点根本不够用,建议调大到 65535:

worker_rlimit_nofile 65535;

注意,这个值还受系统级限制 ulimit -n 的影响,最好把 /etc/security/limits.conf 里的 nofile 也一起调大,否则 Nginx 启动时会报错或静默降级。

二、events 块:连接数的关键

events 块控制 Nginx 如何处理连接,最重要的两个参数是 worker_connections 和 use。worker_connections 表示每个 worker 进程能同时保持的最大连接数,它和 worker_processes 的乘积就是理论上限。对于个人站点,设置 4096 或 8192 就足够了:

events {
    use epoll;                  # Linux 下最高效的事件模型
    worker_connections 8192;    # 每个 worker 的最大连接数
    multi_accept on;            # 一次 accept 多个新连接
}

epoll 是 Linux 2.6 内核以后的事件驱动模型,性能远高于默认的 select 模型,Nginx 在 Linux 上编译时通常会自动检测,但显式写出来更保险。multi_accept 开启后,worker 进程会一次性接受所有等待中的新连接,在高并发场景下能明显减少事件循环的唤醒次数。

三、开启 gzip 压缩,立竿见影

对于以文本内容为主的博客站,gzip 是最划算的优化:几乎零成本,效果却立竿见影。HTML、CSS、JavaScript 的压缩率通常能达到 60% 到 80%,也就是说页面体积能缩小到原来的五分之一。在 http 块中添加:

gzip on;
gzip_vary on;
gzip_comp_level 6;                 # 压缩级别,6 是性价比最高的档位
gzip_min_length 1024;              # 小于 1KB 的文件不压缩,避免浪费 CPU
gzip_types text/plain text/css application/json application/javascript
           application/xml image/svg+xml text/javascript application/x-javascript;

注意三点:第一,comp_level 不建议超过 6,级别越高 CPU 消耗越大,收益却递减;第二,gzip_types 必须写全,很多人漏了 application/json 和 application/javascript,导致接口数据和 JS 文件没有压缩;第三,图片、视频这类二进制文件不要放进 gzip_types,它们本身已经是压缩格式,再压一遍只会白白消耗 CPU。配置完成后,用 curl -H "Accept-Encoding: gzip" -I 你的域名 验证响应头里是否出现了 Content-Encoding: gzip。

四、静态资源缓存:让浏览器替你省流量

博客站的图片、CSS、JS 都是不怎么变化的静态文件,完全可以让浏览器缓存起来,用户第二次访问时直接读本地缓存,连请求都不用发。在 server 块中添加 location 规则:

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|woff2?)$ {
    expires 30d;                    # 缓存 30 天
    access_log off;                 # 静态文件不记日志,省磁盘 IO
    add_header Cache-Control "public, max-age=2592000";
}

这里有个小技巧:expires 和 Cache-Control 同时设置是为了兼容不同版本的浏览器。静态文件缓存起来之后,你可以观察一下 Nginx 的 access log,会发现图片和 CSS 的请求量大幅下降,服务器压力小了一大截。

五、keepalive 与连接复用

HTTP/1.1 默认支持 keepalive,即一次 TCP 连接上可以发送多个请求。合理配置 keepalive 能省去反复建立 TCP 连接的握手开销:

keepalive_timeout 65;
keepalive_requests 1000;   # 单条连接上最多处理的请求数,默认 100,调大减少重建连接

如果你的网站配置了反向代理(比如 Nginx 代理后面的 PHP-FPM 或其他后端服务),还要在 upstream 配置中加上 keepalive:

upstream php_backend {
    server 127.0.0.1:9000;
    keepalive 32;   # 每个 worker 保持 32 条空闲连接
}

这里特别容易踩坑:一旦给 upstream 配置了 keepalive,proxy_http_version 必须改为 1.1,并且要清空 proxy 请求头里的 Connection 字段,否则 keepalive 不生效,甚至会出现 502 错误:

location ~ \.php$ {
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_pass http://php_backend;
}

六、HTTPS 性能优化:TLS 1.3 与 OCSP Stapling

启用 HTTPS 之后,TLS 握手本身也会带来延迟。对个人站长来说,最有效的三个优化是:优先使用 TLS 1.3、开启会话复用、开启 OCSP Stapling。TLS 1.3 把握手从两次往返减少到一次,配合会话复用,几乎感觉不到握手开销:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;     # 共享会话缓存
ssl_session_timeout 1d;
ssl_stapling on;                      # OCSP Stapling,减少证书验证延迟
ssl_stapling_verify on;
resolver 8.8.8.8 1.1.1.1 valid=300s;
resolver_timeout 5s;

开启后可以用 openssl s_client -connect 你的域名:443 -status 检查响应中是否包含 OCSP Response。另外建议开启 HSTS,强制浏览器走 HTTPS:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

七、日志与性能:access_log 的取舍

access_log 默认记录所有请求,流量稍大就会产生海量日志,频繁的磁盘写入会拖慢整体性能。个人站长的做法是:静态资源不记日志(前面已配置),动态页面日志开启缓冲:

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

buffer=32k 表示日志先写入内存缓冲区,攒够 32KB 或超过 5 秒才落盘,能大幅减少磁盘 IO 次数。别忘了定期切割日志,否则日志文件会无限膨胀,撑爆磁盘。推荐用 logrotate,配置文件放在 /etc/logrotate.d/nginx:

/var/log/nginx/*.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

八、sendfile 与 TCP 优化:最后一公里的提速

Nginx 处理静态文件时,默认先把文件读进用户空间再通过 socket 发送,中间多了一次内存拷贝。开启 sendfile 之后,数据可以直接从磁盘通过内核发送给网卡,省去用户空间的参与,大文件传输效率提升非常明显。在 http 块中加上:

sendfile on;
tcp_nopush on;     # 数据包攒满再发,配合 sendfile 减少小包数量
tcp_nodelay on;    # 关闭 Nagle 算法,降低交互请求的延迟

tcp_nopush 和 tcp_nodelay 看起来矛盾,一个攒包一个发包,其实它们作用的场景不同:sendfile 传输大文件时用 tcp_nopush 合并数据包,减少网络拥塞;keepalive 连接上的小请求用 tcp_nodelay 保证及时响应。两者配合使用,是 Nginx 官方推荐的配置组合。

九、open_file_cache:把文件句柄缓存起来

每次请求静态文件,Nginx 都要执行一次 open 系统调用。对于热门文件(比如全站共用的 CSS、logo 图片),这完全是重复劳动。open_file_cache 可以把文件描述符、文件大小、修改时间缓存起来,命中缓存的请求直接跳过 open 调用:

open_file_cache max=10000 inactive=60s;   # 最多缓存 1 万个文件,60 秒无访问淘汰
open_file_cache_valid 120s;               # 每 120 秒检查一次文件是否变化
open_file_cache_min_uses 2;               # 访问 2 次以上才缓存
open_file_cache_errors on;                # 缓存文件不存在的错误,避免重复 stat

这个参数对图片站、附件多的站点效果尤其明显。配置完可以用 nginx -t 检查语法,然后 reload,观察 access log 里静态文件的响应时间,通常会有 30% 以上的下降。

十、HTTP/2 与 HTTP/3:协议层面的升级

如果证书配置没问题,强烈建议开启 HTTP/2:它支持多路复用,一个连接上可以并行传输多个资源,彻底解决了 HTTP/1.1 的队头阻塞问题,对页面里有大量 CSS、JS、图片的博客站提升非常明显。在 listen 指令后加 http2 即可(Nginx 1.25.1 之后语法为 listen 443 ssl http2;)。HTTP/3 基于 UDP 的 QUIC 协议,握手更快、弱网环境表现更好,但需要 Nginx 1.25+ 且浏览器支持有限,个人站长可以后续再研究。开启 HTTP/2 后用 Chrome 开发者工具看 Network 面板,协议列显示 h2 就说明生效了。

十一、验证与总结

配置改完后,先执行 nginx -t 检查语法,再执行 nginx -s reload 平滑重载,然后依次验证:curl 看响应头里有没有 Content-Encoding: gzip、Cache-Control、Strict-Transport-Security;再用浏览器开发者工具看 Network 面板的加载时间。我自己的博客在做了这套优化之后,首屏加载时间从 1.8 秒降到了 0.6 秒,TTFB 从 400ms 降到了 120ms 左右,效果非常明显。优化的原则是"一次只改一个参数、改完就压测对比",不要一次性堆一堆配置,出了问题都不知道是哪一项引起的。Nginx 优化的空间还有很多,比如 fastcgi_cache、Lua 扩展、多级缓存等,等以后有机会再单独写一篇。希望这篇文章能帮你把网站的访问速度提上一个台阶。

Last modification:August 3rd, 2026 at 08:18 am

Leave a Comment