Nginx中動態(tài)upstream域名解析失效問題解決的幾種方法
要讓 Nginx 對 upstream 中的域名做運(yùn)行時動態(tài)解析(而非僅啟動時靜態(tài)解析),關(guān)鍵不是簡單加個 resolver,而是必須滿足“變量觸發(fā) + 作用域正確 + 配置兼容”三要素。直接寫 proxy_pass http://api.example.com; 或在 upstream 塊里寫 server api.example.com;,無論有沒有 resolver,都只會解析一次。、
問題根源
# ? 錯誤示例:僅在啟動時解析一次
upstream backend {
server api.example.com:8080; # 啟動時解析,之后永遠(yuǎn)不變
}
location / {
proxy_pass http://backend;
}當(dāng)后端 IP 變化時,Nginx 仍指向舊 IP,導(dǎo)致請求失敗。
解決方案一:使用 resolver 指令(推薦)
基礎(chǔ)配置
http {
# 1. 配置 DNS 解析器(必須放在 http/server/location 層級)
resolver 8.8.8.8 8.8.4.4 valid=10s; # Google DNS,TTL 10秒
resolver_timeout 5s;
server {
listen 80;
location /api/ {
# 2. 使用變量強(qiáng)制動態(tài)解析
set $backend "api.example.com";
proxy_pass http://$backend:8080;
# 3. 關(guān)鍵:配合 resolver 實(shí)現(xiàn)每次請求都解析(或按 TTL 緩存)
proxy_http_version 1.1;
proxy_set_header Host $host;
}
}
}進(jìn)階:Consul/內(nèi)部 DNS 服務(wù)發(fā)現(xiàn)
http {
# 針對 Consul 或 Kubernetes CoreDNS 優(yōu)化
resolver 127.0.0.1:8600 valid=5s; # Consul DNS 端口
resolver_timeout 2s;
# 可選:指定 DNS 搜索域
resolver 10.96.0.10 valid=5s ipv6=off; # K8s CoreDNS,禁用 IPv6 避免延遲
server {
location / {
set $svc "user-service.service.consul";
proxy_pass http://$svc:8080;
# 連接池優(yōu)化:避免頻繁 DNS 查詢影響性能
proxy_connect_timeout 2s;
proxy_send_timeout 5s;
proxy_read_timeout 10s;
}
}
}解決方案二:upstream + resolver 組合(高可用)
需要負(fù)載均衡時,結(jié)合 upstream 動態(tài)解析:
http {
resolver 10.0.0.2 valid=10s;
# 定義 upstream 但使用域名變量
upstream dynamic_backend {
server 0.0.0.0; # 占位,實(shí)際在 location 中解析
# 健康檢查(需要 nginx_upstream_check_module 或商業(yè)版)
check interval=3000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
location / {
# 關(guān)鍵:使用變量觸發(fā) resolver
set $backend_nodes "app.service.consul";
# 通過 Lua 或 split_clients 實(shí)現(xiàn)動態(tài)選擇(見方案三)
proxy_pass http://$backend_nodes;
}
}
}解決方案三:Lua 動態(tài)解析(OpenResty)
最靈活的方式,完全控制解析邏輯:
http {
resolver 127.0.0.1:8600;
server {
location / {
access_by_lua_block {
local resolver = require "resty.dns.resolver"
-- 1. 創(chuàng)建 DNS 客戶端
local dns, err = resolver:new{
nameservers = {"127.0.0.1", {"127.0.0.1", 8600}},
retrans = 2,
timeout = 1000,
}
-- 2. 查詢 SRV 記錄(Consul 推薦)
local answers, err = dns:query("user-service.service.consul",
{qtype = dns.TYPE_SRV})
-- 3. 動態(tài)選擇節(jié)點(diǎn)(加權(quán)隨機(jī))
if answers then
local target = answers[math.random(1, #answers)]
ngx.var.target_host = target.target
ngx.var.target_port = target.port
else
-- 降級到靜態(tài)配置
ngx.var.target_host = "127.0.0.1"
ngx.var.target_port = "8080"
end
}
set $target_host "";
set $target_port "";
proxy_pass http://$target_host:$target_port;
}
}
}解決方案四:Nginx Plus(商業(yè)版)
如果預(yù)算允許,Nginx Plus 提供原生動態(tài)解析:
upstream backend {
zone upstream_backend 64k;
# 關(guān)鍵:resolve 參數(shù)啟用動態(tài) DNS
server api.example.com:8080 resolve;
# 健康檢查
health_check interval=5s fails=3 passes=2;
}
server {
location / {
proxy_pass http://backend;
health_check;
}
}關(guān)鍵配置參數(shù)詳解
| 參數(shù) | 說明 | 推薦值 |
|---|---|---|
| valid=10s | DNS 緩存 TTL | 微服務(wù)環(huán)境 5-10s,穩(wěn)定服務(wù) 60s |
| ipv6=off | 禁用 IPv6 解析 | 純 IPv4 環(huán)境建議關(guān)閉,避免延遲 |
| resolver_timeout | 單次 DNS 查詢超時 | 2-5s |
| resolver 位置 | 必須在 http{}、server{} 或 location{} | 通常放 http{} 全局 |
常見問題排查
1. 解析不生效(仍使用舊 IP)
# ? 錯誤:直接寫死域名,不會觸發(fā) resolver proxy_pass http://api.example.com:8080; # ? 正確:使用變量強(qiáng)制動態(tài)解析 set $backend "api.example.com"; proxy_pass http://$backend:8080;
2. 日志中出現(xiàn) no resolver defined
# 錯誤原因:location 中使用了變量,但上級未定義 resolver
# 解決:確保 resolver 在 http 或 server 層級定義
http {
resolver 8.8.8.8; # 必須在這里定義,不能只在 location
}3. DNS 查詢延遲高
# 優(yōu)化:本地 DNS 緩存 + 連接池
resolver 127.0.0.1 valid=5s; # 指向本地 dnsmasq/unbound
upstream backend {
keepalive 100; # 連接池,避免每次新建連接
keepalive_timeout 60s;
keepalive_requests 1000;
}生產(chǎn)環(huán)境完整配置模板
http {
# DNS 配置(多可用區(qū)冗余)
resolver 10.0.0.2 10.0.0.3 valid=10s ipv6=off;
resolver_timeout 3s;
# 日志記錄解析詳情(調(diào)試用)
log_format dns_log '$remote_addr - $upstream_addr [$time_local] '
'"$request" $status $body_bytes_sent '
'upstream: "$upstream_addr" '
'resolve: "$upstream_http_host"';
upstream app_servers {
zone app_zone 64k;
keepalive 100;
# 占位 server,實(shí)際在 location 中動態(tài)解析
server 127.0.0.1:1 backup; # 備用,防止啟動失敗
}
server {
listen 80;
access_log /var/log/nginx/access.log dns_log;
location / {
# 動態(tài)解析核心配置
set $backend_host "app.service.consul";
set $backend_port "8080";
proxy_pass http://$backend_host:$backend_port;
# 錯誤降級
proxy_intercept_errors on;
error_page 502 503 504 = @fallback;
# 連接優(yōu)化
proxy_connect_timeout 3s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 2;
}
location @fallback {
internal;
return 503 '{"error":"Service Unavailable","retry_after":10}';
}
}
}核心要點(diǎn):resolver + 變量 是實(shí)現(xiàn)動態(tài) DNS 的黃金組合,務(wù)必確保使用 $variable 形式編寫 proxy_pass,否則 Nginx 會優(yōu)化為啟動時靜態(tài)解析。
到此這篇關(guān)于Nginx resolver指令解決動態(tài)upstream域名解析失效問題的文章就介紹到這了,更多相關(guān)Nginx upstream域名解析失效問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解nginx upstream 配置和作用
- Nginx upstream的5種權(quán)重分配方式分享
- nginx報錯connect() failed(111: Connection refused)while connecting to upstream解決方法
- Nginx根據(jù)url中的path動態(tài)轉(zhuǎn)發(fā)到upstream的實(shí)現(xiàn)
- 關(guān)于nginx沒有跳轉(zhuǎn)到upstream地址的解決
- Nginx?upstream使用教程
- nginx報錯upstream sent invalid header的解決
- Nginx日志中request_time和upstream_response_time區(qū)別
- Nginx負(fù)載均衡之upstream模塊簡介與使用詳解
- Nginx之upstream被動式重試機(jī)制的實(shí)現(xiàn)
- Nginx動態(tài)配置upstream的使用小結(jié)
- Nginx中upstream模塊的具體用法
- nginx的反向代理upstream失敗重試策略詳解
相關(guān)文章
國外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例
這篇文章主要介紹了國外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例,使用fastcgi配置模式,需要的朋友可以參考下2014-07-07
由于Nginx配置文件問題導(dǎo)致打不開網(wǎng)站unknown directive的解決
這篇文章主要介紹了由于Nginx配置文件問題導(dǎo)致打不開網(wǎng)站unknown directive,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06

