Nginx多级网关轮询负载均衡需L1、L2、L3各层协同:L1轮询分发至L2集群,L2按路径/头轮询至业务子集群,L3轮询真实实例并集成健康检查与协议适配,须保障协议透传、超时递增及追踪头全链路传递。

实现多级网关下的 Nginx 轮询负载均衡,核心不是简单套用 upstream + proxy_pass,而是让轮询逻辑在每一层网关中各司其职、协议一致、链路可控。L1、L2、L3 各层都可使用轮询(或加权轮询),但目标不同:L1 轮询的是 L2 网关集群,L2 轮询的是业务子集群入口,L3 才轮询真实服务实例。
第一层:L1 入口网关用轮询分发到 L2 集群
L1 是流量统一入口,它不直连业务服务,而是把请求轮询转发给多个 L2 网关节点(比如按地域或职能划分的 api-gw-east、api-gw-west)。关键点是:
- 定义多个 upstream,每个代表一个 L2 逻辑集群,例如:
upstream l2_api_cluster {<br> server 10.10.1.10:8080;<br> server 10.10.1.11:8080;<br> server 10.10.1.12:8080;<br>} - 启用基础容错:
max_fails=2 fail_timeout=30s,避免单个 L2 节点临时不可用导致整条链路中断 - 必须透传原始 Host 和客户端 IP:
proxy_set_header Host $host;、proxy_set_header X-Real-IP $remote_addr;、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
第二层:L2 业务网关用轮询路由到具体服务组
L2 接收 L1 转发来的 HTTP 流量,再按路径、Header 或域名做二次轮询分发。例如将 /user/ 请求轮询到 user-svc 集群,/order/ 轮询到 order-svc 集群:
- 用
map指令动态提取路由标识:map $request_uri $backend_upstream {<br> ~^/user/ user_backend;<br> ~^/order/ order_backend;<br> default default_backend;<br>} - 为每个业务定义独立 upstream,启用轮询(可加权):
upstream user_backend {<br> server 172.16.0.100:8000 weight=3;<br> server 172.16.0.101:8000 weight=1;<br>} - 开启连接复用:
keepalive 32;+proxy_http_version 1.1;,减少 L2 到 L3 的建连开销
第三层:L3 服务接入层用轮询对接真实后端实例
L3 是最靠近应用的一层,负责将请求最终轮询到 Pod、VM 或容器实例。这一层的轮询需兼顾健康状态和协议兼容性:
- 每个 upstream 显式配置健康检查(开源版需配合
nginx_upstream_check_module):upstream app_instances {<br> server 192.168.10.5:8080 max_fails=2 fail_timeout=30s;<br> server 192.168.10.6:8080 max_fails=2 fail_timeout=30s;<br> check interval=3 rise=2 fall=3 timeout=1;<br>} - 若后端是 gRPC,必须启用 HTTP/2:
proxy_http_version 2.0;,并清除 Connection 头:proxy_set_header Connection ''; - 轮询本身无需额外声明——Nginx 默认即轮询;如需差异化,直接加
weight即可
协同要点:确保轮询在多级中不“断层”
多级轮询容易出问题的地方不在单层配置,而在层级之间脱节。必须保障:
- 协议透传一致:L1 终结 SSL 后,L2/L3 必须使用 HTTP/1.1 或 HTTP/2 显式声明,不能混用
- 超时逐层递增:L1 timeout > L2 timeout > L3 timeout(例如 60s > 30s > 10s),避免上游过早中断等待
-
全链路追踪头透传:如
X-Request-ID、X-B3-TraceId等需逐层proxy_set_header传递,便于问题定位 -
避免 DNS 缓存干扰:upstream 中尽量用域名而非 IP,并配置
resolver和valid=30s支持服务发现更新


















