Nginx轉(zhuǎn)發(fā)404問題的排查和思考
項(xiàng)目背景
項(xiàng)目是 toG 項(xiàng)目,部署的網(wǎng)絡(luò)環(huán)境是一個(gè)大的內(nèi)網(wǎng)環(huán)境(又具體分為內(nèi)網(wǎng)和內(nèi)網(wǎng)互聯(lián)網(wǎng)區(qū)),項(xiàng)目涉及到小程序、前端、后端(又包括 JAVA 和 GO 兩個(gè)項(xiàng)目)的部署。整體的部署拓?fù)鋱D大致如下:
虛擬 IP 映射:大多數(shù)內(nèi)網(wǎng)如何需要暴露對(duì)外訪問,會(huì)在出口的核心路由上配置一個(gè)虛擬的 IP 作為對(duì)外的統(tǒng)一訪問入口。比如你的內(nèi)網(wǎng)地址及端口是 10.13.3.177:8080,則通過虛擬 IP 映射的地址及端口可能是:10.31.31.253:8080。
在這個(gè)業(yè)務(wù)流程程,訪問路徑是:公網(wǎng)(小程序前臺(tái))-> 內(nèi)網(wǎng)互聯(lián)網(wǎng)區(qū)【10.31.1.142(nginx + 小程序后臺(tái))】 -> 【10.31.31.253 -> 10.13.3.177(nginx+后端)】 -> 【10.233.1.2 -> 172.13.7.249(nginx+后端)】。其中 10.13.3.177 和 172.13.7.249 是兩臺(tái)虛擬機(jī),虛擬機(jī)上部署了nginx 和 后端服務(wù)。
PS:上述所有的 IP 均已做過處理,非正式 IP。
問題
訪問步驟及問題節(jié)點(diǎn):
- 1、小程序訪小程序后臺(tái)服務(wù)
- 2、小程序后臺(tái)服務(wù)發(fā)起調(diào)用到
10.31.31.253
(這里實(shí)際上是10.31.1.142
要調(diào)用10.233.1.2
的服務(wù),因?yàn)?10.31.1.142
不能直接訪問10.233.1.2
,所以借用10.31.31.253
來實(shí)現(xiàn)一層轉(zhuǎn)發(fā)邏輯)。
這里會(huì)涉及到兩個(gè)轉(zhuǎn)發(fā),
10.31.31.253
對(duì)應(yīng)的10.13.3.177
這臺(tái)機(jī)器上的 nginx 需要將10.31.1.142
的請(qǐng)求轉(zhuǎn)發(fā)給10.233.1.2
10.233.1.2
對(duì)應(yīng)的 nginx 需要將請(qǐng)求到當(dāng)前機(jī)器的后臺(tái)服務(wù)上
在轉(zhuǎn)發(fā)時(shí)通過 10.31.31.253
調(diào)用 10.233.1.2
時(shí)出現(xiàn) 404,10.233.1.2
調(diào)用本機(jī)后端服務(wù)時(shí)也出現(xiàn) 404;還有一個(gè) 502 是 10.31.1.142
訪問 10.31.31.253
出現(xiàn)的。下面是分析問題的大體過程和解決辦法。
因端口映射導(dǎo)致的訪問 502 問題
前面提到 10.31.31.253
和 10.233.1.2
均是 虛擬 IP ,10.31.31.253:8805
端口映射到虛擬機(jī) 10.13.3.177
上的端口是 18805,10.13.3.177
上 nginx 配置的監(jiān)聽端口是 18805,所以 10.31.1.142
在訪問的第一跳是 10.31.31.253:8805
,但在實(shí)際排查中發(fā)現(xiàn), 10.31.1.142
訪問的是 10.31.31.253:18805
,所以出現(xiàn) 502 問題。
狀態(tài)碼 502 表示 HTTP 協(xié)議中的 "Bad Gateway",通常用于表示服務(wù)器作為網(wǎng)關(guān)或代理時(shí)遇到了問題。這個(gè)錯(cuò)誤通常會(huì)在一個(gè)服務(wù)器作為中介時(shí),無法從另一個(gè)服務(wù)器獲取有效響應(yīng)以滿足客戶端請(qǐng)求時(shí)出現(xiàn)。
proxy_pass 轉(zhuǎn)發(fā) url 丟棄路徑導(dǎo)致的 404 問題
根據(jù)前面的背景,實(shí)際上兩個(gè) 404 問題均是因?yàn)檫@個(gè)原因?qū)е隆?code>10.31.1.142 發(fā)起的請(qǐng)求是 10.31.31.253:8805/miniapp/user/case
, nginx access.log 的日志如下:
"POST /miniapp/user/case HTTP/1.1" 404 153 "-" "Java/1.8.0_351" "POST /miniapp/user/case HTTP/1.1" 404 153 "-" "Java/1.8.0_351" "POST /miniapp/user/case HTTP/1.1" 404 153 "-" "Java/1.8.0_351"
因?yàn)檫@個(gè)請(qǐng)求不是 10.31.31.253 對(duì)應(yīng)的 10.13.3.177 這臺(tái)機(jī)器上的服務(wù)處理,而是直接轉(zhuǎn)發(fā)給 10.233.1.2 對(duì)應(yīng)的 172.13.7.249 機(jī)器的,因此這里出現(xiàn) 404,因?yàn)槭寝D(zhuǎn)發(fā)到 172.13.7.249 時(shí)沒有找到相應(yīng)的資源。查看 249 機(jī)器上的 nginx 訪問日志
"POST /user/case HTTP/1.0" 404 153 "-" "Java/1.8.0_351" "POST /user/case HTTP/1.0" 404 153 "-" "Java/1.8.0_351" "POST /user/case HTTP/1.0" 404 153 "-" "Java/1.8.0_351"
可以看到, 249 這臺(tái)機(jī)器上的請(qǐng)求變成了 /user/case,丟失了 /miniapp 這個(gè) prefix,10.13.3.177 機(jī)器的 nginx 配置如下:
location /miniapp/ { // 主要是這里 proxy_pass http://10.31.31.253:8805/; }
關(guān)于這個(gè)問題,解決方案大致有如下幾種(來源各種技術(shù)文章):
- 1、修改代理配置:將匹配以 /miniapp 開頭的所有請(qǐng)求,并將它們代理到 10.31.31.253:8805,保持請(qǐng)求 URI 不變。
location /miniapp { proxy_pass http://10.31.31.253:8805; }
- 2、使用正則表達(dá)式捕獲和重寫 URI:捕獲以 /miniapp 開頭的請(qǐng)求,并將 /miniapp 后面的部分傳遞給后端服務(wù)器。
location ~ ^/miniapp(/.*)$ { proxy_pass http://10.31.31.253$1; }
- 3、rewrite 重寫:使用 rewrite 指令將 /miniapp 后面的部分提取出來,然后將其傳遞給后端服務(wù)器
location /miniapp/ { rewrite ^/miniapp(/.*)$ $1 break; proxy_pass http://10.31.31.253; }
- 4、保留 location 前綴:就是將 location 前綴保留在 proxy_pass 的后面
location /miniapp/ { proxy_pass http://10.31.31.253:8805/miniapp/; }
經(jīng)測試,方案 1 和 方案 4 是可以解決 404 問題的。其中方案 4 是**有病治病的邏輯,轉(zhuǎn)發(fā)丟棄則就加上。**這兩個(gè)問題對(duì)于了解 nginx proxy_pass 配置的同學(xué)來說應(yīng)該一眼就可以看到問題所在,但是 大多數(shù)時(shí)候,我們會(huì)忽略那些看起來并不是很顯眼的東西,比如 /
。
proxy_pass 配置以 / 結(jié)尾和不以 / 結(jié)尾的區(qū)別
- 以 / 結(jié)尾的proxy_pass配置
location /miniapp/ { proxy_pass http://10.31.31.253:8805/; }
這種配置方式?jīng)]有斜杠 / 結(jié)尾,意味著 Nginx 會(huì)將原始請(qǐng)求的 URI 原封不動(dòng)地傳遞給后端服務(wù)器。例如,如果原始請(qǐng)求是 http://10.31.1.142/miniapp/user/case,那么 Nginx 會(huì)將它代理到http://10.31.31.253:8805/miniapp/user/case。
所以說,如果你希望將請(qǐng)求映射到后端服務(wù)器的根目錄,則可以使用以斜杠 /
結(jié)尾的配置。如果你希望保持URI不變,可以使用不以 /
結(jié)尾的配置。
關(guān)于 proxy_pass 以及 location
網(wǎng)上關(guān)于這兩個(gè)介紹的文章非常多,本篇不做過多的闡述。
- proxy_pass 指令用于定義 Nginx 的 反向代理 功能。它指定了將客戶端請(qǐng)求代理到的后端服務(wù)器的地址。
- location 指令用于匹配客戶端請(qǐng)求的 URI,然后定義如何處理這些請(qǐng)求。
問題其實(shí)不是很復(fù)雜,主要還是對(duì)于 nginx 的一些配置作用不大清楚,另外就是在實(shí)際排查過程中,因?yàn)殒溌泛途W(wǎng)絡(luò)環(huán)境問題走了很多彎路;但是如果把這些信息梳理清楚了,就會(huì)撥云見日;問題就在那里,復(fù)雜的是過程。
以上就是Nginx轉(zhuǎn)發(fā)404問題的排查和思考的詳細(xì)內(nèi)容,更多關(guān)于Nginx轉(zhuǎn)發(fā)404的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
nginx-rtmp-module構(gòu)建流媒體直播服務(wù)器實(shí)戰(zhàn)指南
本文主要介紹了nginx-rtmp-module構(gòu)建流媒體直播服務(wù)器實(shí)戰(zhàn)指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02nginx+lua單機(jī)上萬并發(fā)的實(shí)現(xiàn)
nginx是我們最常用的服務(wù)器,常用于做內(nèi)容分發(fā)和反向代理,本文主要介紹了nginx+lua單機(jī)上萬并發(fā)的實(shí)現(xiàn),有興趣的可以了解下2021-05-05nginx設(shè)置資源緩存實(shí)戰(zhàn)詳解
這篇文章主要介紹了nginx設(shè)置資源緩存實(shí)戰(zhàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10nginx如何使用openssl自簽名實(shí)現(xiàn)https登錄
這篇文章主要介紹了nginx使用openssl自簽名實(shí)現(xiàn)https登錄,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08使用LDAP實(shí)現(xiàn)Nginx用戶認(rèn)證的示例
本文主要使用Nginx和LDAP實(shí)現(xiàn)用戶認(rèn)證,通過配置Nginx和安裝nginx-auth-ldap模塊,可以實(shí)現(xiàn)基于LDAP的認(rèn)證邏輯,下面就來介紹一下,感興趣的可以了解一下2024-12-12