代理(proxy),即中間人,它代替客戶端發送請求給服務器,收到響應後再轉給客戶端。一般意義上的代理是從用戶的角度講的,用戶經過某個代理能夠訪問多個網站,這個代理是靠近用戶的,好比某些公司可能須要限制員工所訪問的網站,就會在網絡出口處放置一個代理來作過濾。nginx
反向代理(reverse proxy),本質上跟代理是一回事,只不過是從服務器的角度講的,是靠近服務器的。好比某個網站有多個服務器,提供一樣的功能,通常會在網絡入口處放一個代理,接收客戶端的請求,再基於某種策略(好比輪轉)轉發給後端服務器,這樣能夠提升整個系統的服務能力。nginx 就是一種常見的 HTTP 協議反向代理。git
nginx 中常見的反向代理指令有兩個:proxy_pass
和 fastcgi_pass
,前者使用標準的 HTTP 協議轉發,後者使用 FastCGI 協議轉發,用於 PHP 等架構的環境。在我要說的這個域名問題上,它們行爲是同樣的,因此下面僅以 proxy_pass
爲例。github
一個最簡單的反向代理配置以下:後端
server { location / { proxy_pass https://github.com; } }
其做用是將全部請求轉發到 github.com。注意此處寫的是域名,而非 IP。咱們知道在真正發起請求前,是須要將域名解析成 IP 的,對於 github.com 來講,在個人環境上它會被解析成兩個 IP:192.30.253.112 和 192.30.253.113,TTL 都是 50s,以下圖:緩存
那麼使用上面這個配置,nginx 是何時作這件事情的呢?答案是啓動的時候,只作一次,解析結果會被緩存下來,也就是徹底無視 TTL,後續全部的請求轉發,都是直接使用緩存下來的 IP,不會再作任何域名解析。對於 github.com 這種返回多個 IP 的狀況,nginx 在轉發時會自動對 IP 列表進行輪轉。服務器
可使用 sudo tcpdump -n -i any port 53
抓包來驗證這個行爲。注:53 是 DNS 服務的默認端口。網絡
那麼問題來了,IP 變了怎麼辦?有什麼辦法讓 nginx 自動從新解析域名嗎?架構
resolver 8.8.8.8; server { location / { set $servers github.com; proxy_pass http://$servers; } }
如上,經過使用變量($servers
)的方式能夠強制 nginx 遵照域名解析結果的 TTL,過時後自動從新解析。不過這種寫法有個反作用,如此配置後 nginx 不會自動使用系統 /etc/resolve.conf
的配置,此時必須使用 resolver
指令手動給它指定一個 DNS 服務器。tcp
其中 8.8.8.8是谷歌的開源免費DNS,國內的有114.114.114.114.若是是內網域名,須要制定內網的DNS服務器。網站
參看地址:
https://github.com/inetfuture/blog/issues/4
https://www.nginx.com/blog/dns-service-discovery-nginx-plus/