← 返回文章列表

04 // 正文

Nginx 反向代理与负载均衡实战:从静态托管到集群分流

如果说 Apache 是"什么都干的老实人",那么 Nginx 就是"跑得飞快又面面俱到"的多面手。作为现代运维的标配,Nginx 既是性能优异的 Web 服务器,又是最流行的反向代理与负载均衡器。本文从一个空白的服务器出发,一步步带你完成静态站点托管、反向代理、负载均衡和 HTTPS 配置,最后给出高频故障的排障思路。

为什么选 Nginx

相比老牌 Web 服务器,Nginx 采用事件驱动的异步架构,单个进程能轻松扛住数万并发连接。它最擅长的三件事:

  • 静态文件服务:处理图片、CSS、JS 等资源效率极高
  • 反向代理:把请求转发给后端应用,隐藏真实服务地址
  • 负载均衡:将流量分发到多台后端,提升可用性与吞吐

💡 小知识

Nginx 发音是 "engine-x",不是"恩吉克斯"。运维圈里装过的逼,都是从这里开始的。

安装与目录结构

主流发行版都有打包好的 Nginx,一行命令装好:

# Debian / Ubuntu
sudo apt update && sudo apt install nginx -y

# RHEL / CentOS / Rocky
sudo dnf install nginx -y

装完后先理解配置目录,不同发行版略有差异:

路径 作用
/etc/nginx/nginx.conf 主配置文件,一般只动 http 块里的 include
/etc/nginx/sites-available/ 站点配置存放处(Debian 系)
/etc/nginx/sites-enabled/ 软链接启用站点(Debian 系),常用 ln -s 挂进来
/etc/nginx/conf.d/ RHEL 系直接放 .conf 即被加载
/var/log/nginx/ access.logerror.log 日志目录
⚠️ 提醒:改完任何配置,先跑 nginx -t 校验语法,再 systemctl reload nginx 平滑重载。直接 restart 会瞬间断开所有连接,能 reload 就别 restart。

实战一:托管一个静态站点

假设站点文件放在 /var/www/blog,我们希望访问 example.com 时返回这些文件。新建一个站点配置:

# /etc/nginx/sites-available/blog
server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/blog;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # 静态资源开启缓存
    location ~* \.(css|js|png|jpg|gif|svg|ico)$ {
        expires 7d;
        add_header Cache-Control "public, max-age=604800";
    }
}
# 启用站点并重载
sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
sudo nginx -t
sudo systemctl reload nginx

try_files $uri $uri/ =404 的含义:先按请求路径找文件,找不到就找目录,再找不到就返回 404。这是静态站点的标准写法。

实战二:反向代理到后端应用

现在后端有个 Java / Python / Node 应用跑在 127.0.0.1:8080,我们不想让用户直接访问它,而是统一从 Nginx 入口进入:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_set_header 是反向代理的黄金搭档,缺一个都可能踩坑:

请求头 作用
Host 把原始域名传给后端,否则后端拿到的永远是 Nginx 的地址
X-Real-IP 透传真实客户端 IP,做日志和风控必备
X-Forwarded-For 记录完整的转发链,多个代理时逐级追加
X-Forwarded-Proto 告诉后端原始请求是 http 还是 https,避免重定向到错误协议
📌 注意:很多应用(如 Spring Boot、WordPress)如果拿不到 X-Real-IP,会把所有访问者都记为 Nginx 的内网 IP。运维排障时先看这几个头有没有配齐。

实战三:负载均衡多台后端

一台后端不够用了,准备两台应用服务器。用 upstream 定义一组后端,再让 proxy_pass 指向它:

upstream backend_servers {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=1;
    server 192.168.1.12:8080 backup;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_servers;
        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;
    }
}

Nginx 默认支持四种负载均衡算法,可通过 upstream 内的指令选择:

算法 写法 特点
轮询(默认) 不写即为轮询 按顺序依次分发,配合 weight 调整权重
权重 server ... weight=3; 高配机器分更多请求
IP 哈希 ip_hash; 同一 IP 固定打到同一后端,适合有会话状态的服务
最少连接 least_conn; 分给当前连接数最少的后端,应对长短请求混合的场景

上面的配置里还有一个隐藏功能:故障转移。Nginx 会主动探测后端可用性(默认 max_fails=1fail_timeout=10s),连续失败的后端会被"摘除"10 秒,请求自动打到健康节点;backup 标记的机器平时不参与,只有全部后端都挂了才会顶上。

实战四:开启 HTTPS

网站要有证书才能上 HTTPS。个人和小项目强烈推荐 Let's Encrypt 的免费证书,配合 certbot 自动续期:

# 安装并签发证书(需要域名已解析到本机)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com

# 证书签发后,certbot 会自动帮你改好配置,再手动补一个强制跳转

如果证书已经就绪,也可以手写 HTTPS 站点:

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;   # http 强制跳转 https
}

server {
    listen 443 ssl;
    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;

    location / {
        proxy_pass http://backend_servers;
        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;
    }
}
⚠️ 注意:手写证书路径时,文件属主与权限要正确(私钥建议 600)。配置报错时先看 /var/log/nginx/error.log,最常见的提示是 "cannot load certificate"。

高频排障:502 与 404

反向代理场景下,两个错误码占了九成的问题:

  • 502 Bad Gateway:Nginx 连不上后端。依次检查后端进程是否存活、端口是否监听(ss -lntp)、防火墙是否放行、proxy_pass 地址是否写对
  • 404 Not Found:多半是 location 匹配问题或后端返回了 404,用 curl -v 直连后端对比,能快速定位是 Nginx 还是应用的问题

排障三板斧,屡试不爽:

  1. nginx -t 确认配置语法没问题
  2. ss -lntp 确认 80 / 443 / 后端端口都在监听
  3. tail -f /var/log/nginx/error.log 看实时报错

最佳实践建议

  • 配置即代码:每个站点一个配置文件,命名清晰(如 example.com.conf),方便回溯
  • 先 nginx -t 再 reload:生产环境改配置永远先校验语法
  • 透传真实 IP:反向代理务必配齐 X-Real-IPX-Forwarded-For
  • 给静态资源加缓存expires 一行指令,能卸下大量后端压力
  • 日志要归档:大流量站点用 logrotate 定期切割日志,避免撑爆磁盘
  • 后端记得做健康检查:应用本身要暴露健康端点(如 /health),配合 Nginx 的 fail 机制自动摘除故障节点
Nginx 最迷人的地方在于:它用一个极简的配置文件,把静态托管、反向代理、负载均衡、SSL 终结全部统一起来。理解 server(虚拟主机)、location(路径匹配)、upstream(后端池)这三个概念,你就掌握了 Nginx 的大部分世界。

从静态站点到反向代理,从单机到集群,再到 HTTPS 加持,这套组合拳已经足以撑起一个小型乃至中型站点的访问压力。下一步可以试试给 Nginx 配上缓存(proxy_cache)或限流(limit_req),让它在生产环境里跑得更稳。

相关资源