Nginx 域名解析超時

使用阿里雲ddns動態域名解析,綁定公司IP,然後用nginx做反向代理。發現公司的ip變化了,通過nginx代理的服務報超時錯誤,總是報找不到後端連接地址。如果沒有通過nginx,而是直接通過域名訪問是沒有問題的。查看了下日誌,發現nginx日誌裏面的域名解析還是解析到原來綁定的ip地址,於是猜想可能nginx有域名解析緩存。果不其然,圍繞nginx域名緩存問題,網上也有出現類似問題。

nginx 報錯信息如下

[error] 1828#0: *146807 upstream timed out (110: Connection timed out) while connecting to upstream, client: 106.122.174.199, server: xxx.zhaodao.info, request: "GET / HTTP/1.1", upstream: "http://106.122.xxx.xxx:xxx/", host: "xxx.zhaodao.info"

找到了知乎一篇文章,分析的挺不錯的,轉載一下。

-------------------------------------------------------------------

 

背景:

此處只針對nginx向後端做代理,且後端代理爲域名形式 的這種情況做分析

1、正常情況下 啓動nginx後(或者 -t / reload nginx時),nginx會通過操作系統配置的DNS服務器去解析域名對應的IP

2、當nginx配置文件中的所有涉及到的域名都可以被正常解析到以後,才能啓動(或者檢查/重新加載)通過

3、這裏需要提醒一點,在 ../sbin/nginx -t 或者 ../sbin/ngins -s reload 只是檢查域名是否可以解析通過,並不會在此時緩存域名對應IP,只有在通過nginx第一次向proxy_pass後端對應的域名做代理數據轉發時,這裏nginx會通過操作系統配置的DNS服務器解析域名,此時纔會緩存域名對應的IP,且會緩存很長時間,甚至一個月(整個過程均有生產實例證明,且抓包驗證)

 

我遇到的問題:

生產的實例

1、我們內網的數據通過nginx轉發到第三方合作公司對應的域名,此處簡稱爲 域名A

2、第三方公司的域名A做了CDN,對應多個IP(IP1,IP2,IP3...),且隨時都有可能因某種原因,丟棄其中一個IP

3、某一天該第三方公司將他們的域名A對應的地址IP3廢棄不用了,域名不再往IP3上解析了

4、但是我們的nginx因爲曾經請求域名A時緩存了IP3,導致後續的許多交易數據仍舊是給IP3發送,造成交易失敗,這種情況在我們沒有reload nginx之前,存在了2周左右,說明nginx緩存這個IP3緩存了很長時間,這就是造成了我們交易失敗的原因(當時排查了好幾天),後來多方聯繫覈對後,才知道第三方公司早在3周前就廢棄了這個IP3,(可能爲了全網的DNS都刷新,域名A不再向IP3解析後,但是IP3所對應的服務器還繼續沿用了一段時間,所以我們是在廢棄後的第二週纔開始報錯)

 

分析與解決:

1、既然是因爲nginx緩存域名對應IP的DNS記錄造成的,那麼怎麼才能解決呢,方法有兩種:

(1)、手動reload nginx,讓nginx重新解析域名,這個時候解析到域名對應的IP是最新的,不會包含已經被廢棄的IP3

(2)、設置nginx的DNS緩存時間,比如600s失效,然後重新去解析

 

2、方法(2)當然是最好的,但是nginx的DNS緩存時間在哪裏設置呢,我沒有找到!

3、但是我找到另外一種方法 -- nginx 的 resolver

 

nginx的resolver 解決方案

1、默認nginx會通過操作系統設置的DNS服務器(/etc/resolv.conf)去解析域名

2、其實nginx還可以通過自身設置DNS服務器,而不用去找操作系統的DNS

3、下面來講一個這個resolver

示例配置如下:

server {
       listen      8080;
       server_name localhost;
       resolver 114.114.114.114 223.5.5.5 valid=3600s;
       resolver_timeout 3s;
       set $qq "www.qq.com";
       location / {
          proxy_pass http://$qq;
       }
   }

 

參數說明:

# resolver 可以在http全局設定,也可在server裏面設定

# resolver 後面指定DNS服務器,可以指定多個,空格隔開

# valid設置DNS緩存失效時間,自己根據情況判斷,建議600以上

# resolver_timeout 指定解析域名時,DNS服務器的超時時間,建議3秒左右

#注意:當resolver 後面跟多個DNS服務器時,一定要保證這些DNS服務器都是有效的,因爲這種是負載均衡模式的,當DNS記錄失效了(超過valid時間),首先由第一個DNS服務器(114.114.114.114)去解析,下一次繼續失效時由第二個DNS服務器(223.5.5.5)去解析,親自測試的,如有任何一個DNS服務器是壞的,那麼這一次的解析會一直持續到resolver_timeout ,然後解析失敗,且日誌報錯解析不了域名,通過頁面拋出502錯誤。

#重點:如上例,在代理到後端域名http://www.qq.com時,千萬不要直接寫在proxy_pass中,因爲server中使用了resolver,所以必須先把域名定義到一個變量裏面,然後在 proxy_pass http://$變量名,否則nginx語法檢測一直會報錯,提示解析不了域名

 

後記

整個過程親測,沒有問題

如果有其他更好的方式或者見解,請回復一起探討哈

轉載自

作者:黑板擦
鏈接:https://www.zhihu.com/question/61786355/answer/268735267
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章