stream模块专用于tcp/udp四层转发,不解析http协议,不支持路径、header或host等七层路由,仅适用于mysql、redis、grpc(裸tcp)等非http协议代理。

Stream 模块不是用来做微服务 HTTP 路由的,它不解析 HTTP 协议,也不支持基于路径、Header 或 Host 的七层分发。想用它“汇聚微服务端口”,必须明确一个前提:你代理的是 非 HTTP 协议的四层服务——比如 gRPC(裸 TCP)、自定义二进制协议、数据库连接、或直接暴露的 TCP 服务端口。
确认你的微服务是否适合 Stream 代理
很多团队误以为“所有微服务都能走 Stream”,结果配置成功却转发失败。关键看通信协议:
- 如果你的服务监听在 8080 端口且使用 HTTP/1.1 或 HTTP/2,请用
http块 +upstream+proxy_pass,这是标准做法; - 如果你的服务是 gRPC over raw TCP(未封装在 HTTP/2 里)、Dubbo TCP 协议、Thrift 二进制流,或只是个监听 9000 端口的 TCP 回显服务——这才属于 Stream 的适用范围;
- 常见误区:把 Spring Cloud Gateway 或 Nacos 注册中心的 HTTP 管理端口(如 8848、9999)用 Stream 转发,会导致连接建立但无法交互,因为底层仍是 HTTP。
正确配置 Stream 实现端口汇聚
Stream 配置与 http 块平级,不能嵌套在 http 内。典型结构如下:
stream {
upstream micro_cluster {
server 10.10.2.5:7001 weight=2;
server 10.10.2.6:7001 max_fails=2 fail_timeout=15s;
server 10.10.2.7:7001 backup;
}
server {
listen 7000;
proxy_pass micro_cluster;
proxy_timeout 10s;
proxy_responses 1;
}
}
-
listen 7000是对外统一入口端口,客户端只需连这个; -
upstream列出所有后端微服务实例的真实地址和端口(注意:不是服务名,除非你启用了 DNS 解析并配置了resolver); -
weight、max_fails、backup等参数都可用,但不支持ip_hash(需启用stream_geoip_module扩展); -
proxy_timeout控制连接空闲超时,对长连接协议(如 gRPC 流式调用)建议设为 0(禁用)或调大; - 若后端是 TLS 加密的 TCP 服务(如 mTLS gRPC),需额外启用
stream_ssl_module并配置证书。
与微服务注册中心联动的现实约束
Stream 本身不支持服务发现。你不能像 Spring Cloud 那样自动感知新节点上线或下线。生产中常用两种补救方式:
-
静态配置 + 定期热重载:用脚本从 Consul/Etcd 拉取服务列表,生成
upstream配置,再执行nginx -s reload; -
OpenResty + Lua 动态解析:在
server块中用balancer_by_lua_block调用 API 获取实时节点,但该能力不在原生 Nginx 中,需 OpenResty; - 注意:Nginx 官方 stream 模块不支持健康检查探针(如 TCP connect 检测),只能靠
max_fails+fail_timeout做被动摘除。
为什么别强行用 Stream 替代 HTTP 代理
如果微服务走的是标准 HTTP,硬套 Stream 会丢失关键能力:
- 无法透传
X-Real-IP、X-Forwarded-For,下游服务拿不到真实客户端 IP; - 无法改写请求头、重写 URL、注入认证 Token;
- 无法按
location /api/order做路径路由,所有流量只能打到同一组后端; - 日志中看不到 HTTP 状态码、响应时间、URI,只有连接建立/断开事件。











