开始使用 nginx 的实战负载均衡指南

许多开发者只把 nginx 当作“反向代理 + 静态文件服务器”,但实际上它是一个功能强大的软件负载均衡器。如果你既负责服务器管理,又能熟练使用 nginx,就能在流量高峰时显著提升服务的稳定性和性能。

本文面向初级–中级开发者,将一次性整理以下内容:

  • 负载均衡概念
  • nginx 负载均衡的配置方法
  • 常用算法(round robin、least_conn、ip_hash 等)
  • 健康检查(Health Check)
  • 常用选项

1. 什么是负载均衡?



负载均衡(load balancing) 简单来说,就是:

“将请求均匀分发到多台服务器,避免单台服务器过载”

为什么需要?

  1. 防止流量暴涨:即使在高峰期也不让单台服务器宕机。
  2. 水平扩展(Scale Out):通过增加服务器数量来提升吞吐量,而不是单纯提升硬件规格。
  3. 高可用性:即使一台服务器失效,流量也能自动切换到其他服务器,保持服务可用。

nginx 在架构中的位置

典型结构如下:

客户端 → nginx(负载均衡器 / 反向代理) → 多台应用服务器

nginx 接收请求后,将其转发到后端的某一台服务器。


2. 理解 nginx 负载均衡的基本结构

nginx 配置中,负载均衡主要由两部分组成:

  1. upstream 块:定义“后端服务器池”。
  2. server / location 块:决定哪些请求转发到哪个 upstream。

下面给出最简单的示例。

http {
    upstream app_backend {
        server 10.0.0.101:3000;
        server 10.0.0.102:3000;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://app_backend;

            # 代理默认头
            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;
        }
    }
}

这段配置的含义

  • upstream app_backend:把 10.0.0.101:300010.0.0.102:3000 两台服务器聚合成一个池。
  • proxy_pass http://app_backend;:将客户端请求转发到该池中的一台服务器。
  • 如果未指定算法,默认使用 round robin

3. 负载均衡算法类型



nginx 提供多种分发策略,选择合适的算法能显著提升性能。

3.1 基础:Round Robin

默认算法,配置方式:

upstream app_backend {
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}
  • 第一次请求 → 服务器1
  • 第二次请求 → 服务器2
  • 第三次请求 → 再次服务器1 …

优点:实现简单,适用于大多数场景。 缺点:不考虑服务器当前负载。


3.2 least_conn(最少连接)

upstream app_backend {
    least_conn;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}

将新请求路由到当前连接数最少的服务器。适用于请求处理时间差异较大的服务。

推荐场景: * 某些请求耗时长,其他请求很快。 * 服务器规格相近,但请求模式不均衡。


3.3 ip_hash(同一 IP 同一服务器)

upstream app_backend {
    ip_hash;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;
}

基于客户端 IP 进行哈希,保证同一 IP 的请求始终走同一台服务器,常用于需要粘性会话的场景。

优点:实现简单,适合旧版会话存储在服务器内存的情况。 缺点:服务器增删会导致映射大幅变化;若客户端 IP 通过代理隐藏,效果失效。


3.4 权重(weight)分发

当服务器规格不同时,可通过权重控制流量比例。

upstream app_backend {
    server 10.0.0.101:3000 weight=3;
    server 10.0.0.102:3000 weight=1;
}

服务器1:服务器2 = 3:1 的请求比例。


4. 健康检查与故障服务器处理

要让负载均衡器真正“聪明”,必须能自动剔除失效服务器

nginx 开源版默认支持被动健康检查

4.1 max_fails / fail_timeout

upstream app_backend {
    server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
    server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
}
  • max_fails=3:连续 3 次失败后将服务器标记为不健康。
  • fail_timeout=30s:在 30 秒内不再向该服务器发送请求,之后再次尝试。

失败判定通常基于 502/503/504 响应或连接失败。


4.2 proxy_next_upstream

决定在何种错误情况下转发到下一台服务器。

location / {
    proxy_pass http://app_backend;
    proxy_next_upstream error timeout http_502 http_503 http_504;
}

仅在指定错误发生时才重试,避免无谓的延迟。


5. 实战示例:简单 Web 服务负载均衡

假设你有两台 Node.js 服务器,监听 3000 端口:

  • 10.0.0.101:3000
  • 10.0.0.102:3000

5.1 nginx 配置示例

http {
    upstream app_backend {
        least_conn;

        server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
        server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 80;
        server_name myservice.com;

        location / {
            proxy_pass http://app_backend;

            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_read_timeout 60s;
            proxy_connect_timeout 5s;
            proxy_send_timeout 10s;
        }
    }
}

重载 nginx 后:

  • 所有请求先到 nginx,再根据最少连接分发到 Node.js 服务器。
  • 服务器连续失败时会被自动剔除。

6. HTTPS(SSL)终止 + 负载均衡

生产环境几乎都使用 HTTPS。常见做法是让 nginx 负责 SSL 终止,内部使用 HTTP。

http {
    upstream app_backend {
        least_conn;
        server 10.0.0.101:3000;
        server 10.0.0.102:3000;
    }

    server {
        listen 443 ssl;
        server_name myservice.com;

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

        location / {
            proxy_pass http://app_backend;

            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;
        }
    }

    # HTTP → HTTPS 重定向
    server {
        listen 80;
        server_name myservice.com;
        return 301 https://$host$request_uri;
    }
}
  • 客户端与 nginx 之间使用 HTTPS。
  • nginx 与后端服务器之间使用 HTTP(内部网络安全即可)。

7. 会话问题:是否需要粘性会话?

过去常见的做法是把会话存放在服务器内存,要求同一用户始终访问同一台服务器。可以用 ip_hash 简单实现,但现代方案更推荐:

  • 将会话存放在 Redis 等外部存储。
  • 使用 JWT 让应用无状态。

若能在应用层去除状态,负载均衡器只需做流量分发,扩展更友好。


8. 常用调优点

8.1 keepalive

重用后端连接可提升性能。

upstream app_backend {
    least_conn;
    server 10.0.0.101:3000;
    server 10.0.0.102:3000;

    keepalive 32;
}

server {
    location / {
        proxy_pass http://app_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}
  • keepalive 32:每个 worker 最多保持 32 条 keepalive 连接。

8.2 缓冲与超时

location / {
    proxy_pass http://app_backend;

    proxy_buffering on;
    proxy_buffers 16 16k;
    proxy_busy_buffers_size 64k;

    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
}
  • 超时过短会导致 504 Gateway Timeout。
  • 根据实际流量与后端性能调整。

9. nginx 负载均衡的引入策略(分阶段)

如果已有单台服务器运行,建议按以下步骤扩容:

  1. 第一阶段:将 nginx 作为反向代理引入。 * 客户端 → nginx → 单台应用服务器。 * 处理 SSL、缓存、静态文件等。
  2. 第二阶段:复制应用服务器,配置 upstream。 * 将两台服务器加入 upstream,开启负载均衡。
  3. 第三阶段:启用健康检查与监控。 * 配置 max_failsfail_timeoutproxy_next_upstream。 * 集成 Prometheus + Grafana 或 ELK 进行日志/指标收集。
  4. 第四阶段:根据流量模式微调算法与参数。 * 选择 least_connweight。 * 调整 keepalive、缓冲、超时等。

结语

nginx 的负载均衡功能远不止于“反向代理”。通过合理配置 upstream、算法、健康检查、HTTPS 终止等,你可以轻松提升服务的可用性与性能。掌握这些技巧后,当流量增长时,你就能快速搭建一个更稳健、更可扩展的基础设施。

image