nginx中proxy_pass小斜槓

nginx中proxy_pass小斜槓

1. 故事背景

相信做微信公衆號開發的朋友都知道,要想在微信中預覽效果,必須使用域名訪問.很多朋友使用內網穿透工具.不僅不好用還不穩定.所以,發揮臉厚吃天下的態度,向公司it申請了一個子域名指向了阿里雲一臺ecs的80端口.可是後來,端口不夠用了.本着就近原則,又找到IT小哥,能再好心的再映射一個8080端口.那知傲嬌的小哥一臉鄙夷眼睛看着我,對不起子域名只能80端口.不湊巧的時,我的ecs也只開放了80端口.此時只有一個域名,我要映射多個服務器.是時候放出大器nginx了.訴求很簡單

  1. 訪問 demo.herbert.com/dev1/json.do 映射內網地址 192.168.10.2:8080/dev1/json.do
  2. 訪問 demo.herbert.com/dev2/xxx.html 映射內網地址 192.168.10.2:8081/xxx.html

2. 解決問題三部曲,文檔搜索和測試

查看官方文檔,我們選擇 tengine 翻譯的官方文檔.在頁面[模塊參考目錄]找到[ngx_http_proxy_module]鏈接,點擊進入以後搜索proxy_pass.一定會找到以下兩個說明

  • 如果proxy_pass使用了URI,當傳送請求到後端服務器時,規範化以後的請求路徑與配置中的路徑的匹配部分將被替換爲指令中定義的URI:
location /name/ {
    proxy_pass http://127.0.0.1/remote/;
}
  • 如果proxy_pass沒有使用URI,傳送到後端服務器的請求URI一般客戶端發起的原始URI,如果nginx改變了請求URI,則傳送的URI是nginx改變以後完整的規範化URI:
location /some/path/ {
    proxy_pass http://127.0.0.1;
}

這段說明晦澀難懂,還出現一個很多人搞不清楚的名稱 URI ,當然我也是那個很多人,爲此我搜索了URI URL的區別,期間還冒出了一個URN,頭都大了,看了十分鐘沒找到滿意的答案.姑且我麼認爲就是地址中的某一部分吧.

簡單理解下第一點,如果 proxy_pass 配置值後邊包含/,最終得到的路徑,會去掉location配置的path,再結合請求地址中location配置之後可能存在的內容.兩者相結合成一個新的地址.按照官方提供的配置.我們假設

  • 該nginx的訪問域名是 wx.464884492.com
  • 用戶訪問的地址是 wx.464884492/name/herbert/

根據提供的第一種配置,nginx得到的真實地址示意圖如下:

最後有斜槓示意圖

再簡單理解下第二點,如果 proxy_pass 配置值後邊不包含/,最終得到的路徑,proxy_pass配置值加上location配置path以及之後的path.兩者結合成一個新地址,按官方提供配置,我們假設

  • 該nginx的訪問域名是 wx.464884492.com
  • 用戶訪問的地址是 wx.464884492/some/path/herbert/

根據提供的第二種配置,nginx得到的真實地址示意圖如下:

最後無斜槓示意圖

所以簡單總結就是

  • 如果proxy_pass配置值 包含 /去掉 匹配路徑部分
  • 如果proxy_pass配置值 不包含 /保留 匹配路徑部分

3. 結果驗證

從nginx官網下載解壓修改nginx.conf文件中http模塊如下:

...
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    client_max_body_size   20M;
    server {
        listen       80 default_server;
        server_name  127.0.0.1;
        location / {  
            proxy_pass http://127.0.0.1;
        }
        location /name/  {
            proxy_pass http://127.0.0.1/remote/;
        }
        location /some/path/ {
           proxy_pass http://127.0.0.1;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
...

雙擊nginx.exe運行分別在瀏覽器中訪問一下地址

由於我配置並沒有具體root,訪問頁面最終的地址是找不到.所以頁面會出現 An error occurred 的錯誤頁.不過我們剛好可以在錯誤日誌印證我們上面的結果.我們上邊的示意圖採用了域名的方式說明,如果想得到示意圖上的結果,需要在host文件中添加配置wx.464884492.com 127.0.0.1同時在nginx配置文件server_name改成wx.464884492.com

打開logs目錄下error.log日誌文件,我們就會發現我們剛訪問的信息以及最終轉換的真實地址信息都乖乖的顯示在那裏,主要信息如下:

瀏覽器訪問 http://127.0.0.1/name/herbert/
nginx 給我的訪問日誌
2019/12/06 14:21:32 [alert] 15384#12716: *9206 1024 worker_connections are not enough while connecting to upstream, 
client: 127.0.0.1, server: 127.0.0.1, 
request: "GET /remote/herbert/ HTTP/1.0", 
upstream: "http://127.0.0.1:80/remote/herbert/", host: "127.0.0.1"

瀏覽器訪問 http://127.0.0.1/some/path/herbert/
nginx 給我的訪問日誌
2019/12/06 14:21:35 [alert] 15384#12716: *11251 1024 worker_connections are not enough while connecting to upstream, 
client: 127.0.0.1, server: 127.0.0.1, 
request: "GET /some/path/herbert/ HTTP/1.0", 
upstream: "http://127.0.0.1:80/some/path/herbert/", host: "127.0.0.1"

4. 解決問題

有了以上知識我的訴求就完美解決了.

  • demo.herbert.com/dev1/json.do 映射內網地址 192.168.10.2:8080/dev1/json.do

對應配置

location /dev1/ {  
 proxy_pass http://192.168.10.2:8080;
}
  • 訪問 demo.herbert.com/dev2/xxx.html 映射內網地址 192.168.10.2:8081/xxx.html

對應配置

location /dev2/ {  
 proxy_pass http://192.168.10.2:8081/;
}

5. 總結

凡事多總結中沒有壞處,以上那麼多其實就一句話,有槓去掉,無槓保留,雖然小,但解決的步驟一個不少.

歡迎感興趣的朋友關注我的微信訂閱號"小院不小",或者點擊下方的二維碼關注。我將多年開發中遇到的難點,以及一些有意思的功能,體會都會一一發布到我的訂閱號中。需要本文nginx配置文件可以在公衆號中回覆nginx1

微信關注【小院不小】

閒來無事,採用cocos creator開發了一個小遊戲,感興趣的朋友一個可以來玩玩

小遊戲坦克俠

有喜歡聊技術朋友也歡迎入羣,若二維碼失效可加我微信回覆前端

微信羣

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