nginx stream模块不支持weight参数,因其工作在传输层,仅支持连接级透传;替代方案包括ip哈希+多upstream分组、ssl_preread+sni映射、或使用nginx plus/haproxy等外部工具。

明确不支持 weight 的原因
Stream 层工作在 OSI 第四层(传输层),不解析应用层协议,也不维护连接状态或会话上下文。它只做连接级透传,因此负载策略只能基于连接建立成功率和健康状态,无法像 HTTP 模块那样做请求级加权轮询。
如果你在 `stream { upstream xxx { server 10.0.1.1:8080 weight=2; } }` 中写 weight,nginx -t 会直接报错:invalid parameter "weight"。
用 IP 哈希 + 多 upstream 实现近似权重效果
虽然不能直接设权重,但可通过多个 upstream 分组 + `hash $remote_addr consistent;` 控制客户端固定路由,再配合不同监听端口或域名(SNI)分流到不同分组,间接达成“按比例分配”的目标。
- 把后端服务按期望比例拆成多组:比如 A 组占 70%,B 组占 30%
- 为每组单独定义 upstream,并各自绑定独立 listen 端口(如 9001 → A 组,9002 → B 组)
- 前端通过 DNS 轮询、客户端配置或网关调度,让 7 成流量打到 9001,3 成打到 9002
这本质是外部调度,不是 Nginx 内部加权,但稳定可控,适合长期运行的服务。
用 ssl_preread + map + 动态 upstream 实现 SNI 权重分流
适用于 TLS 流量(如 HTTPS、gRPC over TLS)。虽然仍无 weight,但可通过 `map` 构建不同域名对应不同 upstream,再结合 DNS 解析比例或客户端接入策略,实现逻辑上的权重分配。
- 启用 ssl_preread on;,提取客户端 TLS 握手中的 SNI 域名
- 用 map 将域名映射到不同 upstream 名称(如 app1.example.com → backend_v1,app2.example.com → backend_v2)
- 每个 upstream 内部可配多个 server,用 least_conn 或 hash $remote_addr 均衡单组内节点
例如:对外统一用 443 端口,但根据 SNI 把 api-v1.example.com 流量导向含 3 台机器的 upstream,api-v2.example.com 导向含 1 台机器的 upstream —— 效果上接近 3:1 权重。
用第三方模块或外部工具补足
若必须原生支持权重且不可妥协,有两个现实路径:
-
使用 Nginx Plus:商业版支持
health_check和weight参数(仅限 stream upstream),但需付费授权 - 引入外部负载均衡器:如 HAProxy(支持 tcp-check + weight)、Envoy 或 MetalLB(K8s 场景),让 Nginx 专注做 SSL 卸载或简单透传
开源 Nginx 社区版目前无计划加入 stream weight 支持,官方文档也明确标注该功能缺失。











