Nginx四层stream模块不支持resolver,需通过HTTP代理+动态proxy_pass或外部服务发现解决;若必须四层,可用Lua+Redis实现动态上游;生产环境推荐HAProxy、Envoy等原生支持DNS动态解析的专用组件。
Nginx 的四层负载均衡(
块)默认不支持运行时 DNS 解析,
指令在
上下文中有效,但在原生
模块中
不可用
。这是关键前提——直接在
里写
会报错:“
directive is not allowed here”。
要解决四层场景下后端地址动态变更问题,必须绕过
的限制,采用“
HTTP 层兜底 + 动态 proxy_pass
”或“
外部服务发现集成
”两类可行路径。
四层本身不支持 resolver,需切换到 HTTP 代理模式
Nginx 官方
明确不支持
、
、变量插值等 DNS 动态能力。若后端是 TCP 服务(如数据库、Redis、自定义协议),但其地址由域名提供(如
),不能靠
直接解析,而应:
将该 TCP 服务通过 HTTP 封装(如用 Envoy 或 Nginx + Lua 做协议桥接),再走
块的
;
或改用支持 DNS 轮询的四层替代方案(如 HAProxy 的
+
)。
如果业务允许且协议兼容(例如后端实为 HTTP API),最简实践就是放弃
,改用
配置:
✅ 这样就能实现:每次请求都按
缓存 DNS 结果,后端 IP 变更后最多 30 秒内自动生效。
使用 Lua + Redis 实现四层级动态上游决策
若必须坚守四层(比如代理 MySQL、PostgreSQL),可借助
在
或
中查 Redis 获取最新 IP 列表,并写入共享字典或临时变量,再配合
实现运行时节点选择:
启动时或定时从 Redis 拉取
;
在
中轮询或哈希选取一个地址;
调用
触发实际连接。
此方式完全绕过 DNS 解析限制,把服务发现逻辑外移,更可控、可监控。
优先考虑专用四层动态代理组件
Nginx 不是为高频率 IP 变更设计的四层网关。生产环境中建议评估以下替代方案:
HAProxy
:原生支持
、
、
,可配置健康检查 + DNS 刷新(
避免启动阻塞);
Envoy
:通过 EDS(Endpoint Discovery Service)对接 Kubernetes Endpoints 或 Consul,实时同步后端列表;
Traefik / Skipper
:内置服务发现,自动监听集群事件并热更新 upstream。
这些工具对“域名→IP→健康状态→权重→连接池”的全链路管理,比硬套 Nginx 更自然。
不复杂但容易忽略。
streamresolverhttpstreamstream { ... }resolverresolverstreamngx_stream_core_moduleresolvervaliddb-prod.internalstreamhttpresolver + valid + proxy_pass $variableresolversserver ... init-addr last,libc,nonestreamhttphttp {
resolver 127.0.0.53 valid=30s;
map $arg_service $backend {
default "api.default.svc.cluster.local";
"payment" "payment-v2.svc.cluster.local";
"notify" "notify-canary.svc.cluster.local";
}
server {
listen 80;
location /api/ {
set $upstream "http://$backend";
proxy_pass $upstream;
proxy_set_header Host $backend;
}
}
}valid=30snginx-lua-moduleinit_worker_by_lua_blockaccess_by_lua_blockbalancer_by_lua_blockmysql-primary: ["10.1.2.10:3306", "10.1.2.11:3306"]balancer_by_lua_blockbalancer.set_current_peer(ip, port)resolversresolve-type Acheck resolversinit-addr libc,none