当前位置: 代码网 > 服务器>服务器>Linux > Nginx生产级配置优化指南

Nginx生产级配置优化指南

2026年08月26日 Linux 我要评论
线上 nginx 配置这事,看着简单——官方文档给的示例改改就能跑。但跑起来和跑得好是两码事。很多人装完 nginx 就拿默认配置上线,worker 进程开一个,连接数不调,g

线上 nginx 配置这事,看着简单——官方文档给的示例改改就能跑。但跑起来和跑得好是两码事。很多人装完 nginx 就拿默认配置上线,worker 进程开一个,连接数不调,gzip 不开,静态文件不缓存,等流量上来了才发现各种 502 和 504。这篇就把生产环境 nginx 的调优经验从头到尾过一遍。

先说版本。2026 年 7 月,nginx 稳定版到了 1.30.4(mainline 1.31.3)。1.30 这个版本带来了不少实用特性:early hints(103 状态码)、到后端的 http/2 代理、upstream sticky session、multipath tcp 支持,还有一个细节改动——默认代理 http 版本改成了 1.1 并开启 keep-alive,以前要手动配的现在默认就有了。但线上别用 mainline,稳定版更靠谱。

worker 进程和连接数调优

nginx 的进程模型是 master + worker。master 负责管理,worker 负责干活。默认配置里 worker_processes 是 1,也就是只有一个 worker 在处理请求,这在多核机器上纯属浪费。

# 自动按 cpu 核心数启动 worker
worker_processes auto;

设成 auto 是最省心的做法,nginx 会根据 cpu 核心数自动启动对应数量的 worker。如果你想手动控制,就填具体数字,一般跟 cpu 核心数一致。

worker_connections 是每个 worker 能同时处理的最大连接数。默认 1024,生产环境太保守了。

events {
    worker_connections 10240;
    # 允许一个 worker 同时接受多个连接
    multi_accept on;
}

10240 是个比较稳妥的值,根据机器内存调整。每个连接大概占 256 字节内存,10240 个连接也就 2.5mb,不用担心内存问题。multi_accept on 让 worker 一次性接受所有新连接,而不是一个一个来,高并发场景下能减少延迟。

最大连接数还有一个系统层面的限制:文件描述符。worker_processes * worker_connections 不能超过系统的 ulimit -n。生产环境一般把系统文件描述符设到 65535 或更高:

# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535

nginx 配置里也加一行:

worker_rlimit_nofile 65535;

keepalive 配置

keepalive 是提升性能的低成本手段。客户端跟 nginx 之间保持连接复用,避免每次请求都重新握手。nginx 1.30 默认到后端的代理已经用 http/1.1 + keep-alive 了,但前端的 keepalive 还是要配。

http {
    # 客户端长连接超时,65 秒覆盖大部分浏览器默认超时
    keepalive_timeout 65;
    # 单个长连接最大请求数,设够大避免频繁重建连接
    keepalive_requests 1000;
}

到后端的长连接也要配,不然每个请求都新建一条到后端的 tcp 连接,开销不小:

http {
    upstream backend {
        server 127.0.0.1:8080;
        # 到后端的长连接池大小
        keepalive 32;
    }

    server {
        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            # 清除 connection 头,让长连接生效
            proxy_set_header connection "";
        }
    }
}

keepalive 32 表示为每个 worker 预留 32 个到后端的长连接。后端应用如果不支持 keep-alive(比如某些 cgi 程序),这配置不生效,但现在的应用服务器基本都支持。

gzip 压缩别忘开

默认 nginx 的 gzip 是关的,这太常见了。一个 200kb 的 json 接口,开了 gzip 能压到 30kb 左右,带宽直接省 85%。线上不开 gzip 等于白扔带宽钱。

http {
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/json application/javascript
               text/xml application/xml application/xml+rss text/javascript
               application/rss+xml application/atom+xml image/svg+xml;
    gzip_vary on;
    gzip_proxied any;
}

几个关键参数:gzip_min_length 1k 太小的响应不压缩,压缩开销大于收益。gzip_comp_level 5 是性价比最高的级别,6 以上压缩率提升不明显但 cpu 开销猛增。gzip_types 要把 json 和 js 加上,默认只压缩 text/html。gzip_vary on 加上 vary: accept-encoding 响应头,让 cdn 能正确缓存压缩和非压缩版本。

静态文件缓存策略

静态文件(css、js、图片)是缓存的重点对象。配好了能大幅减少回源请求。

server {
    location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header cache-control "public, immutable";
        # 日志里不记录静态文件请求,减少 io
        access_log off;
    }
}

expires 30d 设置浏览器缓存 30 天。带 hash 的文件名可以用 immutable,告诉浏览器这个文件永远不会变,连条件请求都省了。没带 hash 的文件名别用 immutable,改了文件浏览器不更新就尴尬了。

服务端缓存可以配合 open_file_cache,缓存文件描述符和元数据,减少磁盘 io:

http {
    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

反向代理和负载均衡

反向代理是 nginx 最常用的功能,负载均衡策略直接决定了后端的压力分布。

upstream backend {
    # 加权轮询(默认)
    server 10.0.0.1:8080 weight=3;
    server 10.0.0.2:8080 weight=1;
    server 10.0.0.3:8080 backup;

    # 1.30 新增的 sticky session
    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

默认是加权轮询,weight 大的服务器分到更多请求。backup 表示备用服务器,前面的全挂了才用。

如果你的后端是有状态的(比如 session 存在本地),用 sticky session 让同一个客户端的请求始终打到同一台后端。nginx 1.30 原生支持了 sticky session,以前只有 nginx plus 才有。

最小连接数策略适合后端处理能力不均匀的场景:

upstream backend {
    least_conn;
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
}

ip_hash 适合需要会话保持但不想用 cookie 的场景,按客户端 ip 哈希分配,但同一 nat 出口下的所有用户会打到同一台后端,移动端场景慎用。

ssl/tls 优化

https 性能损耗主要在握手阶段。优化好了,握手开销能降到几乎无感。

server {
    listen 443 ssl;
    http2 on;

    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # 只用 tls 1.2 和 1.3,干掉不安全的旧版本
    ssl_protocols tlsv1.2 tlsv1.3;

    # 优先用服务端密码套件,防止客户端选弱算法
    ssl_prefer_server_ciphers on;
    ssl_ciphers ecdhe-ecdsa-aes128-gcm-sha256:ecdhe-rsa-aes128-gcm-sha256:ecdhe-ecdsa-aes256-gcm-sha384:ecdhe-rsa-aes256-gcm-sha384;

    # session 缓存,减少握手次数
    ssl_session_cache shared:ssl:10m;
    ssl_session_timeout 1d;

    # tls 1.3 session ticket
    ssl_session_tickets on;

    # ocsp stapling,客户端不用自己去查证书状态
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
}

tls 1.3 的握手只需要一次往返,比 1.2 少一轮,延迟能降几十毫秒。ssl_session_cache 让同一个客户端的后续连接复用握手结果,shared:ssl:10m 大约能缓存 4 万个 session。ocsp stapling 把证书状态查询放到服务端,省去客户端额外请求,也能避免某些网络环境下 ocsp 查询失败导致连接变慢。

安全头不能少

安全响应头是低成本高收益的防护手段,配几行就能挡掉一批常见攻击:

server {
    add_header x-frame-options "sameorigin";
    add_header x-content-type-options "nosniff";
    add_header x-xss-protection "1; mode=block";
    add_header referrer-policy "strict-origin-when-cross-origin";
    add_header strict-transport-security "max-age=31536000; includesubdomains";
    add_header content-security-policy "default-src 'self'";
}

x-frame-options 防点击劫持,x-content-type-options 防 mime 嗅探,hsts 强制浏览器后续都走 https。csp 策略按你的实际需求调,default-src 'self' 是最严格的,可能需要放开一些外部资源域名。

502 和 504 怎么排查

这俩是线上最高频的错误,排查思路要清晰。

502 bad gateway 是 nginx 连不上后端。先看后端进程是不是挂了,ps aux | grep your_app 确认进程在不在。进程在的话看端口,netstat -tlnp | grep 8080 确认后端在监听。都正常就查 nginx 的 upstream 配置,ip 和端口对不对。还有一种情况是后端处理太慢,nginx 等不及了,这时候需要调超时:

location / {
    proxy_pass http://backend;
    # 后端响应超时时间
    proxy_read_timeout 60s;
    proxy_connect_timeout 5s;
    proxy_send_timeout 60s;
}

proxy_connect_timeout 是连接后端的超时,一般 5 秒够了——连不上说明后端有问题。proxy_read_timeout 是等待后端响应的超时,如果后端有慢接口,适当调大,但别设成 300s 之类的离谱值。

504 gateway timeout 是连上了后端但后端在规定时间内没返回。这个基本就是后端的问题了——接口太慢、数据库查询卡死、死循环。查后端日志,看慢查询,该加索引加索引,该加缓存加缓存。

nginx 层面能做的是给后端加一层降级保护,避免慢请求拖垮整个连接池:

location / {
    proxy_pass http://backend;
    proxy_next_upstream error timeout http_502 http_504;
    proxy_next_upstream_tries 2;
    proxy_next_upstream_timeout 10s;
}

一个后端超时了自动切到下一个,最多试两次,总超时 10 秒。这样单个后端节点出问题不会让用户干等。

一份可用的生产配置骨架

把上面的配置整合一下,给一份能直接拿来改的生产骨架:

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 10240;
    multi_accept on;
}

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

    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" $request_time';

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

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 65;
    keepalive_requests 1000;

    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/json application/javascript
               text/xml application/xml image/svg+xml;
    gzip_vary on;

    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;

    upstream backend {
        server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
        server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
        keepalive 32;
    }

    server {
        listen 80;
        server_name example.com;
        return 301 https://$host$request_uri;
    }

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

        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;
        ssl_protocols tlsv1.2 tlsv1.3;
        ssl_session_cache shared:ssl:10m;
        ssl_session_timeout 1d;

        add_header x-frame-options "sameorigin";
        add_header x-content-type-options "nosniff";
        add_header strict-transport-security "max-age=31536000";

        location ~* .(js|css|png|jpg|gif|ico|svg|woff2)$ {
            expires 30d;
            add_header cache-control "public, immutable";
            access_log off;
        }

        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header connection "";
            proxy_set_header host $host;
            proxy_set_header x-real-ip $remote_addr;
            proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
            proxy_set_header x-forwarded-proto $scheme;
            proxy_connect_timeout 5s;
            proxy_read_timeout 60s;
        }
    }
}

这份配置覆盖了进程调优、连接复用、压缩、缓存、https、安全头、反向代理这些核心项。拿去改改 ip 和域名就能用。上线前记得跑一下 nginx -t 验证配置语法,改完用 nginx -s reload 平滑加载,不会断已有连接。

nginx 调优不是一次性的事,流量涨了、后端变了、新版本出了功能了,都得回头看看配置是不是还合理。养成习惯,定期 review 一次,比出事了再救火强太多。

以上就是nginx生产级配置优化指南的详细内容,更多关于nginx生产级配置优化的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com