使用阿里雲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
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。