Nginx 高频配置实战:反向代理、动静分离与性能调优

举报
yd_250351897 发表于 2026/10/14 20:13:27 2026/10/14
【摘要】 Nginx 高频配置实战:反向代理、动静分离与性能调优Nginx 是每个后端工程师都绕不开的基础设施。它既是反向代理,又是静态服务器,还是负载均衡å™...

Nginx 高频配置实战:反向代理、动静分离与性能调优

Nginx 是每个后端工程师都绕不开的基础设施。它既是反向代理,又是静态服务器,还是负载均衡器和缓存层。本文抛开"安装与 Hello World",直接聚焦五个线上最高频的配置场景,每个场景都给出可直接复制的配置片段和避坑要点。

场景一:反向代理——一台机器承载多个服务

最常见的诉求:一台云主机上跑着多个端口不同的服务(8080 的 API、3000 的前端、9000 的管理后台),希望通过 80/443 统一入口访问,并按路径分流。

upstream api_backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

server {
    listen 80;
    server_name example.com;

    # /api/* 转发给后端服务
    location /api/ {
        proxy_pass http://api_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;
    }

    # 前端 SPA:history 路由刷新 404 的经典解法
    location / {
        proxy_pass http://127.0.0.1:3000;
        try_files $uri $uri/ /index.html;
    }
}

三个避坑要点:

  1. proxy_pass 末尾带 / 与不带 / 语义完全不同。location /api/ + proxy_pass http://backend/ 会把 /api/user 转成 /user;不带 / 则保留 /api/user 原样转发。选哪种取决于后端路由设计,团队内必须统一。
  2. proxy_set_header Host $host 一定要显式设置。默认透传的是 proxy_pass 中的地址(如 127.0.0.1:8080),后端如果基于 Host 做虚拟主机判断或生成绝对 URL,行为就会错乱。
  3. upstream 里加 keepalive 32 并配合 proxy_http_version 1.1 + 清空 Connection 头,才能复用到后端的长连接。高并发场景下这一项能显著减少 TIME_WAIT 堆积。

场景二:动静分离——让 Nginx 干它最擅长的事

动态请求转发给应用,静态资源交给 Nginx 直接吐,并加上浏览器缓存:

server {
    listen 80;
    server_name example.com;

    # 静态资源:直接读盘 + 长效缓存
    location /static/ {
        alias /data/web/static/;   # 注意 alias 与 root 的区别
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 带 hash 的构建产物可以永久缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|woff2?)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;   # 静态资源不打访问日志,省 IO
    }

    # 入口文件不缓存,保证发版即时生效
    location = /index.html {
        add_header Cache-Control "no-cache";
    }
}

root 与 alias 的区别是面试高频题:root 会把 location 路径拼在根目录后(/static/logo.png → /data/static/logo.png),alias 则是替换 location 前缀(/static/logo.png → /data/web/static/logo.png)。用错了就是经典的 404 灵异事件。

构建产物带 hash 才配 immutable。如果文件名是 app.js 这种固定名,配了一年缓存,用户浏览器将永远拿不到更新——这是"我发了版但用户没生效"的头号原因。

场景三:Gzip 与传输优化——小改动,大提速

http {
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;          # 1-9,CPU 与压缩率的平衡点
    gzip_min_length 1k;         # 小文件不压缩,省 CPU
    gzip_types text/plain text/css application/json 
               application/javascript application/xml+rss 
               image/svg+xml;
}

注意:gzip_types 默认只压缩 text/html。很多新手开了 gzip 却发现 JS/CSS 没压缩,就是因为漏了 gzip_types。gzip_comp_level 建议 4-6,再高收益递减而 CPU 消耗陡增。

另外两个常被忽略的参数:

sendfile on;          # 零拷贝传输,大文件必备
tcp_nopush on;        # 配合 sendfile,积累数据包一次发出
tcp_nodelay on;       # 交互式请求低延迟

场景四:HTTPS 与安全响应头

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

    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;      # 果断放弃 TLS 1.0/1.1
    ssl_prefer_server_ciphers on;

    # HSTS:告诉浏览器以后只用 HTTPS 访问
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options SAMEORIGIN always;
}

# HTTP 全量跳转 HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

HSTS 只在 HTTPS server 块里加,且一旦启用,浏览器在 max-age 内会强制 HTTPS,回退 HTTPS 需要清理浏览器 HSTS 缓存,上线前务必确认全站 HTTPS 可用。

场景五:限流与故障排查

限流防刷

http {
    # 按 IP 限流:每秒 10 个请求,突发 20
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}

server {
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        limit_req_status 429;
        limit_conn conn_limit 10;
        proxy_pass http://api_backend/;
    }
}

被限流的请求返回 429,比让后端被打挂优雅得多。burst=20 nodelay 表示允许 20 个突发请求立即处理,超出部分直接拒绝。

502 与 504 的快速定位

状态码 典型原因 排查命令
502 Bad Gateway 后端进程挂了 / upstream 地址写错 curl -v 127.0.0.1:8080 直连后端
504 Gateway Timeout 后端响应太慢,超过 proxy_read_timeout 看后端日志找慢 SQL/慢接口
499 客户端主动断开(常见于超时取消) 检查客户端超时设置
# 看 Nginx 错误日志(通常 /var/log/nginx/error.log)
tail -f /var/log/nginx/error.log

# 验证配置语法,reload 前必做
nginx -t && nginx -s reload

nginx -t 再 reload要形成肌肉记忆。直接 reload 一个带语法错误的配置,Nginx 会拒绝加载新配置但老 master 还在跑——症状是"改了配置没生效",排查半天才发现是语法错误。

小结

本文覆盖了 Nginx 线上五大高频场景:反向代理透传真实 IP、动静分离与缓存策略、Gzip 传输优化、HTTPS 安全加固、限流与故障排查。这些配置的共同思想是:让 Nginx 承担它擅长的连接管理与静态内容分发,把动态请求高效可靠地转给后端。

建议收藏本文,下次配 Nginx 时直接对照取用。你在生产环境还踩过哪些 Nginx 的坑?欢迎在评论区分享。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。