nginx中proxy_pass写死域名仅启动时静态解析dns,必须配合resolver指令与变量(如proxy_pass http://$backend;)才能实现动态刷新;resolver需显式配置在http或location块中,valid参数控制缓存时效,变量是触发动态解析的必要开关。

直接在 proxy_pass 中写域名(如 proxy_pass http://api.example.com;)会导致 Nginx 仅在启动或重载时解析一次 DNS,之后所有请求都发往缓存的旧 IP——哪怕后端已漂移、扩缩容或 DNS 已更新,Nginx 也不会感知,从而引发连接失败、502 或超时。所谓“解析延迟”,本质是 DNS 缓存未刷新,而非网络延迟。核心解法是启用运行时动态解析,resolver 是必要前提,但单靠它还不够,必须配合变量使用。
resolver 必须显式声明且位置合理
Nginx 不读取系统 /etc/resolv.conf,也不自动继承 DNS 配置。不写 resolver,就无法做任何运行时解析。
- 推荐放在
http块顶层,对全站生效:resolver 223.5.5.5 114.114.114.114 valid=30s ipv6=off; -
valid=30s表示最多缓存 30 秒,过期后强制重查——这是控制“延迟感”的关键参数,设太长(如 300s)会拖慢故障切换,设太短(如 5s)会加重 DNS 查询压力 - 至少配两个 DNS 地址防单点失效;加
ipv6=off可避免无 IPv6 环境下的额外查询耗时
proxy_pass 必须用变量才能触发 resolver
resolver 是工具,变量才是开关。写死域名永远不调用 resolver;只有值为变量时,Nginx 才会在新建连接或缓存过期时主动查 DNS。
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 正确写法(在
location内):set $backend "api.example.com:8000";<br>proxy_pass http://$backend;
- 注意协议头必须完整(
http://或https://),否则不触发解析 - 若用了变量,需手动补
Host头:proxy_set_header Host api.example.com;,否则部分后端可能路由失败
验证是否真正生效
不能只看配置有没有写 resolver,要确认行为是否符合预期:
- 查错误日志:
tail -f /var/log/nginx/error.log,正常会有resolving "api.example.com"记录 - 临时修改该域名的 DNS 解析结果(例如指向一个能抓包的测试 IP),等超过
valid时间后发起请求,观察是否连到新地址 - 用
ss -tnp | grep :80查看 worker 进程实际连接的目标 IP,对比是否已更新
进阶:应对 DNS 查询失败的容错
真实场景中 DNS 服务可能短暂不可达,导致请求卡住或失败:
- 在
resolver后加timeout=3s;(如resolver 223.5.5.5 timeout=3s valid=30s;),避免阻塞 - 搭配
proxy_next_upstream error timeout invalid_header http_502;,让失败请求快速转向其他逻辑路径 - 若用
upstream,可加max_fails=1 fail_timeout=10s;实现节点自动摘除










