002-nginx-proxy_pass、在 nginx 反向代理中使用域名,配置動態域名解析


一、概述

  代理(proxy),即中間人,它代替客戶端發送請求給服務器,收到響應后再轉給客戶端。通常意義上的代理是從用戶的角度講的,用戶通過某個代理可以訪問多個網站,這個代理是靠近用戶的,比如某些公司可能需要限制員工所訪問的網站,就會在網絡出口處放置一個代理來做過濾。

  反向代理(reverse proxy),本質上跟代理是一回事,只不過是從服務器的角度講的,是靠近服務器的。比如某個網站有多個服務器,提供同樣的功能,一般會在網絡入口處放一個代理,接收客戶端的請求,再基於某種策略(比如輪轉)轉發給后端服務器,這樣可以提高整個系統的服務能力。nginx 就是一種常見的 HTTP 協議反向代理。

1.1、反向代理指令

nginx 中常見的反向代理指令有兩個:proxy_pass 和 fastcgi_pass,前者使用標准的 HTTP 協議轉發,后者使用 FastCGI 協議轉發,用於 PHP 等架構的環境。在我要說的這個域名問題上,它們行為是一樣的,所以下面僅以 proxy_pass 為例。

一個最簡單的反向代理配置如下:

server {
    location / {
        proxy_pass https://github.com;
    }
}

1.2、域名解析

其作用是將所有請求轉發到 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 自動重新解析域名嗎?

1.3、配置動態域名解析

resolver 8.8.8.8;

server {
    location / {
        set $servers github.com;
        proxy_pass http://$servers;
    }
}

如上,通過使用變量($servers)的方式可以強制 nginx 遵守域名解析結果的 TTL,過期后自動重新解析。不過這種寫法有個副作用,如此配置后 nginx 不會自動使用系統 /etc/resolve.conf 的配置,此時必須使用 resolver 指令手動給它指定一個 DNS 服務器。

  其中 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/ 

二、反向代理

  注意設置proxy_pass 后,同時需要設置proxy_set_header

proxy_set_header Host js.test.com; 
proxy_pass http://js.test.com/; 

2.1、nginx location proxy_pass 后面的url 加與不加/的區別

  在nginx中配置proxy_pass時,當在后面的url加上了/,相當於是絕對根路徑,則nginx不會把location中匹配的路徑部分代理走;如果沒有/,則會把匹配的路徑部分也給代理走。 

  在nginx中配置proxy_pass時,如果是按照^~匹配路徑時,要注意proxy_pass后的url最后的/,當加上了/,相當於是絕對根路徑,則nginx不會把location中匹配的路徑部分代理走;如果沒有/,則會把匹配的路徑部分也給代理走。

首先是location進行的是模糊匹配

  1)沒有“/”時,location /abc/def可以匹配/abc/defghi請求,也可以匹配/abc/def/ghi等

  2)而有“/”時,location /abc/def/不能匹配/abc/defghi請求,只能匹配/abc/def/anything這樣的請求

下面2種情況分別用http://192.168.1.1/proxy/test.html 進行訪問。

1、proxy_pass后有 / 絕對路徑 不帶走 location 路徑

location  /proxy/ {
    proxy_pass http://127.0.0.1:81/;
}

結論:會被代理到http://127.0.0.1:81/test.html 這個url

擴展1、

location  /proxy/ {
    proxy_pass http://127.0.0.1:81/ftlynx/;
}

結論:會被代理到http://127.0.0.1:81/ftlynx/test.html 這個url。

擴展2、

location  /proxy/ {
    proxy_pass http://127.0.0.1:81/ftlynx;

結論:會被代理到http://127.0.0.1:81/ftlynxtest.html 這個url

2、proxy_pass 后沒有 / ,帶走location路徑

location  /proxy/ {
    proxy_pass http://127.0.0.1:81;
}

結論:會被代理到http://127.0.0.1:81/proxy/test.html 這個url

3、可以通過的rewrite來實現/的功能

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM