欢迎光临
我们一直在努力

Nginx 性能调优与安全加固完全指南:让你的 VPS 承载更高并发

Nginx 是目前最流行的 Web 服务器和反向代理软件之一,全球超过三分之一的网站都在使用它。很多站长买了 VPS 之后,只是简单地用宝塔或者 OnePanel 一键安装 Nginx,然后直接上线网站,从来不去调整默认参数。殊不知,Nginx 的出厂配置其实是以”兼容性优先”为原则的,并没有针对性能和安全做过深度优化。同样一台 2 核 4G 的 VPS,调优前后的并发处理能力可能相差 5 到 10 倍。今天这篇文章,我们就来深入拆解 Nginx 从性能到安全的完整调优方案,每一步都附上配置代码和原理说明。

服务器机房

一、Nginx 核心工作模型与参数调优

要调优 Nginx,首先得理解它的工作模型。Nginx 采用 Master-Worker 多进程架构,Master 进程负责读取配置和维护 Worker 进程,而 Worker 进程负责处理实际的客户端请求。每个 Worker 进程是单线程的,使用事件驱动模型(epoll/kqueue)来异步处理成千上万的并发连接。

这种架构的核心理念是:不要把 Worker 进程数设置得过少,也不要设置得过多。设置太少,CPU 核心利用不充分;设置太多,上下文切换的开销会吃掉性能。推荐的配置是在 nginx.conf 的 events 块和全局块中调整以下参数:

# 通常设为 CPU 核心数,或 auto
worker_processes auto;

# 每个 Worker 能同时打开的最大文件数
worker_rlimit_nofile 65535;

events {
    # 使用 epoll(Linux 上最高效的事件模型)
    use epoll;
    # 每个 Worker 的最大并发连接数
    worker_connections 20480;
    # 允许同时接收多个新连接
    multi_accept on;
    # 事件处理是否轮询
    accept_mutex on;
}

worker_rlimit_nofile 这个参数很多人会忽略。Nginx 处理每个连接都需要打开一个文件描述符,如果不调大系统级的 ulimit 和 Nginx 级别的限制,即使 worker_connections 设得再高,实际能承载的连接数也会被操作系统的文件描述符限制卡住。记得同步在 /etc/security/limits.conf 中添加:

* soft nofile 65535
* hard nofile 65535

multi_accept on 的意思是,当一个 Worker 进程收到有新连接的通知时,它会尝试一次性把所有等待中的连接都接收进来,而不是一个一个地收。在高并发场景下,这个参数能有效提升吞吐量。

二、静态资源缓存策略:让 Nginx 替你扛住大部分流量

对于 Web 应用来说,图片、CSS、JavaScript 等静态资源通常占整体流量的 60% 以上。如果每次用户访问都让 Nginx 去后端应用服务器(如 PHP-FPM、Node.js 或 Python)读取这些文件,不仅浪费后端计算资源,还会显著增加响应时间。正确的做法是让 Nginx 直接处理静态资源,并且充分利用浏览器缓存和 Nginx 自身的缓存机制。

2.1 浏览器缓存控制

通过设置 Cache-ControlExpires 头,可以告诉浏览器哪些文件应该缓存、缓存多久。对于长期不变的文件(如打包后的 JS/CSS),可以缓存一年:

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp)$ {
    expires 365d;
    add_header Cache-Control "public, no-transform, immutable";
    # 关闭访问日志,减少磁盘 I/O
    access_log off;
    # 启用 sendfile,零拷贝发送文件
    sendfile on;
    tcp_nopush on;
}

这里用到了几个关键优化点:sendfile on 让 Nginx 在内核态直接将文件数据从磁盘拷贝到网络套接字,绕过了用户态的数据复制,性能显著提升。tcp_nopush on 在 sendfile 模式下,Nginx 会在数据包积累到一定大小后再发送,减少小包数量,提高网络利用率。

2.2 Nginx 反向代理缓存

如果网站使用反向代理架构(Nginx 在前端、应用服务器在后端),可以开启 Nginx 的代理缓存功能。当用户请求一个页面时,Nginx 先检查本地缓存,如果有就直接返回,不需要穿透到后端服务器:

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

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_cache my_cache;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_valid 200 302 60m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating http_500;
        proxy_pass http://127.0.0.1:8080;

        # 添加缓存状态头,方便排查
        add_header X-Cache-Status $upstream_cache_status;
    }
}

keys_zone=my_cache:10m 意思是分配 10MB 共享内存存储缓存元数据,大约可管理 80,000 个缓存键。max_size=10g 限制缓存体总大小不超过 10GB。proxy_cache_use_stale 是一个很实用的容错机制:当后端服务器超时或出错时,Nginx 可以返回过期的缓存内容,保证服务不中断。

参数 说明 推荐值
proxy_cache_path 缓存存储路径和参数 /var/cache/nginx
keys_zone 缓存元数据内存区 10-20m(每 8 万键约 10MB)
max_size 磁盘缓存上限 磁盘剩余空间的 20-30%
inactive 未被访问的缓存保留时间 60m(60 分钟)

三、Gzip 压缩优化:让内容传输更轻更快

Gzip 压缩是中大型网站的标准配置,但很多人的压缩配置要么没开全,要么压缩级别设得太高导致 CPU 浪费。Nginx 的 Gzip 压缩需要在 http 块中配置:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
    text/plain
    text/css
    text/javascript
    text/xml
    text/js
    application/json
    application/javascript
    application/xml
    application/rss+xml
    image/svg+xml
    font/woff
    font/woff2;

# 对已压缩格式关闭 gzip,避免二次压缩
gzip_disable "msie6";
gzip_disable "\.(mp4|webm|ogg|avi|zip|gz|bz2|rar|jpg|jpeg|png|gif|webp)$";

关键参数说明:gzip_comp_level 5 是在压缩比和 CPU 开销之间取得平衡的经验值。级别 1 压缩最快但体积最大,级别 9 体积最小但 CPU 消耗增加 3-4 倍。经测试,从 5 提升到 9,文件体积仅多压缩 3-5%,但 CPU 时间却翻了近一倍,完全不划算。gzip_min_length 256 的意思是小于 256 字节的文件不压缩,因为压缩这些小文件的开销可能比传输原文还要大。

四、安全加固:防攻击与防扫描配置

VPS 一旦上线公网,就无时无刻不暴露在各种扫描器和攻击脚本的视线下。Nginx 作为第一道防线,可以从以下几个维度进行加固。

4.1 隐藏版本号与敏感信息

# 隐藏 Nginx 版本号
server_tokens off;

# 禁用不必要的 HTTP 方法(只允许 GET/HEAD/POST)
if ($request_method !~ ^(GET|HEAD|POST)$) {
    return 405;
}

# 限制请求 body 大小(防大文件上传攻击)
client_max_body_size 20m;

# 设置缓冲区大小,防缓冲区溢出攻击
client_body_buffer_size 128k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

4.2 防止恶意爬虫和扫描

互联网上存在大量恶意爬虫和漏洞扫描器,它们会不断尝试遍历常见路径(如 /wp-admin、/admin、/.git、/backup 等)。可以在 server 块中添加:

# 禁止访问敏感目录和文件
location ~* (\.git|\.svn|\.hg|\.bzr|\.env|config\.json|composer\.json) {
    deny all;
    return 404;
}

# 根据 User-Agent 拦截恶意爬虫
location / {
    if ($http_user_agent ~* (AhrefsBot|SemrushBot|MJ12bot|DotBot|MegaIndex|Python-urllib|curl|wget) ) {
        return 403;
    }
}

# 限制请求速率(防 CC 攻击)
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s;
location / {
    limit_req zone=one burst=20 nodelay;
}

limit_req_zone 是在共享内存中为每个客户端 IP 维护一个请求计数,rate=30r/s 表示每秒最多处理 30 个请求,超出部分进入 burst 队列等待,nodelay 表示 burst 队列中的请求也会被立即处理但会计入限速统计。这个配置能有效防御慢速 CC 攻击和暴力破解尝试。

4.3 HTTP 安全头

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

五、SSL/TLS 性能优化:兼顾安全与速度

现在启用 HTTPS 已经是建站的基本要求了。但如果 SSL 配置不当,可能会导致页面加载延迟几百毫秒。优化的核心思路是:减少握手次数、选择高效的加密套件、启用会话复用

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 选用现代安全且高效的协议版本
    ssl_protocols TLSv1.2 TLSv1.3;

    # 优先使用性能更好的加密套件
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # 启用 OCSP Stapling,减少客户端验证证书链的时间
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 1.1.1.1 valid=300s;
    resolver_timeout 5s;

    # SSL 会话缓存,复用已建立的 SSL 会话
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # HTTP/2 多路复用
    http2_max_concurrent_streams 128;
}

ssl_session_cache 是一个容易被忽略但效果显著的优化点。启用共享缓存后,客户端在同一台服务器上建立新连接时可以复用之前协商好的 SSL 会话参数,完全跳过完整的 TLS 握手过程。对于 API 接口或者有大量 AJAX 请求的站点,这个配置能减少 1-2 个 RTT 的延迟。

另外,强烈建议开启 HTTP/2(如上配置中的 listen 443 ssl http2)。HTTP/2 的多路复用特性允许在同一个 TCP 连接上并行传输多个资源,消除了 HTTP/1.1 的队头阻塞问题。根据 Google 的实测数据,启用 HTTP/2 后页面加载速度平均提升 15-20%。

六、连接超时与 Keepalive 优化

Nginx 的连接管理直接影响服务器的并发承载能力。如果连接超时设置过长,空闲连接会耗尽 Worker 进程的连接池,导致新连接无法建立。反之,设置过短又会导致频繁断开重连,增加开销。

# 客户端连接超时
keepalive_timeout 30s;
keepalive_requests 1000;

# 代理连接超时
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;

# 后端 upstream 的 keepalive 连接池
upstream backend {
    server 127.0.0.1:8080;
    keepalive 32;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

location / {
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_pass http://backend;
}

keepalive 32 为 upstream 后端保留 32 个保持活动的长连接。需要注意的是,为了使用 upstream keepalive,proxy_http_version 必须设为 1.1,并且清空 Connection 请求头。这一步很多人会忘记配置,导致 keepalive 实际上没有生效。

七、日志调优与磁盘 I/O 优化

在高并发场景下,Nginx 的访问日志写入会成为磁盘 I/O 瓶颈。特别是使用机械硬盘的 VPS,大量的同步日志写入可能导致 Nginx 整体性能下降 20% 以上。以下是几种优化策略:

# 启用日志缓冲区(异步写入)
access_log /var/log/nginx/access.log main buffer=64k flush=5s;

# 静态资源不记录日志
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|woff|woff2)$ {
    access_log off;
}

# 健康检查请求不记录日志
location /health {
    access_log off;
    return 200 "OK";
}

# 错误日志级别调低(生产环境建议 crit 或 error)
error_log /var/log/nginx/error.log crit;

默认情况下,Nginx 每处理一个请求就同步写一次日志,这在高并发时会产生大量的磁盘 I/O 操作。buffer=64k 让 Nginx 先把日志写入 64KB 的内存缓冲区,缓冲区满了再一次性写入磁盘。flush=5s 是保险机制,即使缓冲区没满,最多 5 秒也会强制写一次,避免进程崩溃时丢失日志。

八、实战:完整配置模板

以下是一个融合了上述所有优化要点的完整 Nginx 配置模板,可以直接用于生产环境 VPS:

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log crit;
pid /var/run/nginx.pid;

events {
    use epoll;
    worker_connections 20480;
    multi_accept on;
    accept_mutex on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # 基本优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;

    # 连接超时
    keepalive_timeout 30s;
    keepalive_requests 1000;

    # 请求限制
    client_max_body_size 20m;
    client_body_buffer_size 128k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/plain text/css text/javascript application/json image/svg+xml;

    # 日志优化
    access_log /var/log/nginx/access.log main buffer=64k flush=5s;

    # 速率限制
    limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s;

    # SSH 会话缓存
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # 代理缓存
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*.conf;
}

将这个模板保存到 /etc/nginx/nginx.conf,然后在 /etc/nginx/conf.d/ 下添加你的站点配置。配置生效前先用 nginx -t 测试语法是否正确,确认无误后执行 systemctl reload nginx 热加载。

九、验证调优效果

配置完成后,一定要做基准测试来验证优化效果。推荐使用以下工具:

  • ab (Apache Bench):最基础的压测工具,ab -n 10000 -c 100 http://yourdomain.com/
  • wrk:更强大的现代压测工具,支持多线程和 Lua 脚本
  • siege:支持模拟并发用户和随机 URL 的压测工具
  • nginx-module-vts:Nginx 的虚拟主机状态模块,可以在 Web 页面实时查看连接数、流量、响应码等指标

以 wrk 为例的测试命令:

# 安装 wrk
apt install wrk -y

# 运行压测(10 个线程,100 个连接,持续 30 秒)
wrk -t10 -c100 -d30s --latency https://yourdomain.com/

# 结果示例(调优前:5000 req/s,调优后:25000 req/s)
Running 30s test @ https://yourdomain.com/
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.34ms    3.21ms  89.12ms   82.45%
    Req/Sec   2,512.34   312.56   3,456.00   75.12%
  750,000 requests in 30.00s, 2.15GB read
Requests/sec:  25,000.12
Transfer/sec:    73.41MB

调优前后对比,如果配置得当,Nginx 的 QPS(每秒请求数)通常可以提升 3-5 倍。同时,由于开启了缓存、压缩和日志缓冲,磁盘 I/O 和网络带宽的利用率也会明显改善。

总结

Nginx 的性能调优不是一个一次性的动作,而是一个持续迭代的过程。本文介绍的调优方向涵盖了核心工作参数、静态资源缓存、Gzip 压缩、安全加固、SSL 优化、连接管理、日志调优等八个维度。在实际操作中,建议每次只调整 1-2 个参数,然后用压测工具验证效果,逐步累积找到最适合你 VPS 硬件水平和业务场景的配置组合。

最后提醒两点:第一,调优前一定备份原配置;第二,如果使用宝塔或 1Panel 之类的面板,部分配置可能被面板的管理功能覆盖,需要确认面板是否允许自定义 Nginx 配置。对于追求极致性能的站长,强烈建议脱离面板,直接在命令行下管理 Nginx 配置——虽然前期学习成本高一些,但你能获得对服务器完全的控制权,长远来看回报巨大。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Nginx 性能调优与安全加固完全指南:让你的 VPS 承载更高并发
分享到: 更多 (0)