Nginx 的 upstream 里主机名解析失败,如何避免 Nginx 直接起不来?

upstream 里写域名时 Nginx 启动期解析失败会拒绝启动(host not found in upstream)。解法:upstream 里用 IP 或 127.0.0.1、proxy_pass 用变量+resolver 走运行时解析、或加 backup 兜底。本文给出各方案。

最佳实践
Nginx 的 upstream 里主机名解析失败,如何避免 Nginx 直接起不来?封面

问题本质:upstream 块里的 server 域名配置加载期就要解析成 IP,解析失败 Nginx 直接报 host not found in upstream 拒绝启动/平滑重启。解法按场景:①upstream 里尽量写 IP;②必须用时变域名,把 proxy_pass 改为变量形式并配 resolver(运行时解析,启动不校验);③多后端时加 backup 保底。

方案一:proxy_pass 变量化(运行时解析)

server {
    listen 80;

    location / {
        resolver 223.5.5.5 valid=30s;
        set $upstream "backend.example.com";
        proxy_pass http://$upstream;
    }
}

变量形式的 proxy_pass 不在启动期解析——域名暂时不可达只影响当时的请求(502),不影响 Nginx 自身启动。详解见本系列《让 Nginx 每次 proxy_pass 都重新解析 DNS》。

方案二:upstream 多服务器 + backup

upstream backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 127.0.0.1:8080 backup;   # 全挂了才启用兜底
}

启动期解析的是 IP 就没有域名问题;所有主后端不可用时请求落到 backup(可以是个静态维护页)。

方案三:维护页兜底

location / {
    proxy_pass http://backend;
    error_page 502 503 504 = @fallback;
}
location @fallback {
    return 503 "服务维护中,请稍后再试";
    add_header Retry-After 60 always;
}

用户看到友好提示而不是裸错误。

场景建议

后端形态 建议
固定内网 IP upstream 直接写 IP
K8s Service 名 用变量+resolver 指向集群 DNS(kube-dns/coredns)
云厂商 CLB 域名 变量+resolver
启动期必须可达的强依赖 保留启动校验反而是好事(快速失败)

观测云对照

解析失败的 502 与后端挂掉的 502 要分开看。 error.log 里两类报错的文案不同(host not found vs connect refused),观测云对错误日志的关键字分类统计,让 DNS 抖动这类问题不被误判为应用故障。

常见问题(FAQ)

Q:upstream 里能用变量吗?
A:开源版 upstream 的 server 指令不支持变量;要动态解析就得绕开 upstream 块用 proxy_pass 变量形式(失去负载均衡能力),或用商业版的 resolve 参数。

Q:reload 时解析失败会怎样?
A:reload 失败,旧进程继续跑(不中断服务),但配置没生效;这也是为什么改 upstream 域名要先确认 DNS 已就绪。

Q:容器环境里 Nginx 先于后端启动报错?
A:编排层面解决——compose 的 depends_on + 健康检查,K8s 的 Service DNS 一般已就绪;仍不行就用变量方案容忍启动期解析失败。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台