Nginx 实现动态 DNS 解析必须用变量触发:proxy_pass 必须引用变量(如 $backend),且 resolver 指令需与之同级或外层作用域;否则仅启动时解析一次。

直接在 proxy_pass 中写死域名(如 proxy_pass https://api.example.com;)会导致 Nginx 仅在启动或重载时解析一次 DNS,之后永远使用缓存的 IP。要实现每次请求前(或按设定周期)重新查 DNS,必须用变量触发动态解析——这是唯一被 Nginx 官方支持且稳定生效的方式。
必须同时满足两个条件
缺一不可:
-
proxy_pass 的值必须是变量,例如
proxy_pass http://$backend;,不能是字面量域名 -
resolver 指令必须出现在同级或外层作用域中,比如写在
location或server块内,不能只放在顶层http块(旧版本不识别)
正确配置示例
以下是最小可运行写法:
location /api/ {
resolver 114.114.114.114 8.8.8.8 valid=30s;
set $backend "api.example.com";
proxy_pass https://$backend;
}说明:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
-
resolver指定 DNS 服务器和缓存有效期(valid=30s表示最多 30 秒后重新解析) -
set $backend赋值为纯域名字符串,不带协议或端口(端口可写在proxy_pass中) -
proxy_pass必须引用该变量,且协议头(https://)需明确
常见错误与避坑点
这些写法看似接近,但全部无效:
-
proxy_pass https://api.example.com;—— 没有变量,始终静态解析 -
resolver写在http块,但set和proxy_pass在location内 —— 低版本 Nginx 不继承,建议就近写在location里 -
set $backend "https://api.example.com"; proxy_pass $backend;—— 协议不能塞进变量,会报错或行为异常 -
resolver配置了但 DNS 服务器不通(如防火墙拦截 UDP 53 端口)—— 解析超时后将 fallback 到旧缓存,日志中可能无明显报错
验证是否真正动态生效
靠日志或抓包确认,不要凭感觉:
- 临时修改本地
/etc/hosts或劫持 DNS 返回一个新 IP,等valid时间过后发起请求,看 error log 是否出现新地址连接记录 - 开启
error_log /path/to/error.log debug;,搜索resolving、resolved或connect to关键字 - 用
strace -p $(pgrep nginx) -e trace=connect观察 worker 进程实际连接的目标 IP 是否变化










