关键在于合理配置resolver与变量配合:需设valid和timeout参数,proxy_pass必须用变量触发运行时解析,推荐http块统一声明resolver并搭配upstream resolve实现健康检查与自动dns更新。

要让 proxy_pass 在使用动态域名时既不卡住请求、又不总连错地址,关键不是“加 resolver”,而是“怎么配 resolver + 怎么用变量”。Nginx 默认只在启动时查一次 DNS,IP 变了就失效;而用了变量(比如 $arg_host 或 $upstream)后,又容易每次请求都阻塞查 DNS。优化的核心是:控制查询时机、限制超时、合理缓存。
必须显式配置 resolver 并设 valid 和 timeout
只写 resolver 8.8.8.8; 是无效的——它不会自动作用于静态 proxy_pass http://example.com,也不会默认启用缓存。真正起作用的组合是:
-
resolver 必须带 valid 参数,例如
resolver 223.5.5.5 114.114.114.114 valid=30s;,表示 DNS 结果最多缓存 30 秒,过期后下一次请求才重新查 -
必须搭配 resolver_timeout,如
resolver_timeout 3s;,防止 DNS 查询卡住整个请求(默认是 30 秒,太长) - resolver 可放在
http、server或location块中,但推荐统一放在http块,避免重复声明
proxy_pass 必须通过变量间接引用域名
Nginx 只有在 proxy_pass 值里出现变量时,才会触发运行时 DNS 解析。所以不能直接写 proxy_pass http://api.example.com,而要拆成两步:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 用
set定义变量承载域名,例如:set $backend "api.example.com"; - 再让
proxy_pass指向该变量:proxy_pass https://$backend$request_uri; - 如果域名来自请求参数(如
?upstream=xxx),可直接用$arg_upstream,但要注意校验和白名单,避免 SSRF
优先用 upstream + resolve(适合固定后端列表)
如果你代理的是几个已知的服务名(比如 auth.svc、order.svc),比纯变量更稳的方式是定义 upstream 并加 resolve 参数:
- 在
http块中声明:resolver 8.8.8.8 valid=20s; - 定义 upstream:
upstream payment { server payment-api.example.com resolve; } - location 中直接
proxy_pass http://payment; - 好处是支持健康检查(
proxy_next_upstream)、连接复用(keepalive),且 DNS 更新由 Nginx 自动管理
避免常见坑:超时、缓存过长、IPv6 干扰
这些细节不注意,会导致 502 频发或切换延迟:
- valid 时间别设太长——建议 ≤ 后端 DNS 的 TTL 值的 1/3(例如后端 TTL 是 60 秒,valid 设 20 秒)
- 如果宿主机或容器不支持 IPv6,加上
ipv6=off,避免因 AAAA 查询失败拖慢整体解析 - 不要把 resolver 写在 if 块或嵌套 location 里,Nginx 不支持条件 resolver
- 线上环境慎用
127.0.0.1作为 resolver 地址,除非确认本地 DNS 服务稳定且低延迟










