一文讀懂並實操 Nginx 反向代理

Java後端,選擇

優質文章,及時送達

一文读懂并实操 Nginx 反向代理

作者 | 圈圈的圈

鏈接 | juejin.im/post/5c0e6d606fb9a049f66bf246

前言

代理是個啥

既然要聊反向代理, 那首先得知道代理是個啥吧? 嗯.

正向代理

比如, 你買束花, 想要給隔壁工位的測試妹子小麗表白. 但是又怕被人家直面拒絕太沒面子. 於是你把鮮花委託給平時和小麗一起的測試小夥伴小紅. 讓她幫忙把花送給小麗. 這就是一個簡單的代理過程, 小紅作為代理幫你把花送給了小麗, 當然這種情況在現實中並不推薦使用, 因為難以避免中間商賺差價 .

在上面的例子中, 你作為客戶端(請求方), 想要向服務方(小麗)發起請求. 但是礙於面子你主動找到了第三方(小紅)作為代理向服務方發送請求, 這種情況就是常說的<code>正向代理/<code>. 正向代理在互聯網中的使用主要是科學上網, 你想訪問谷歌但是礙於防火牆你只能通過vpn服務器作為代理才能訪問. 這個時候一般也要找值得信賴的vpn廠商, 避免中間商賺差價 .

一文读懂并实操 Nginx 反向代理

反向代理

關於反向代理的例子, 那就比較多啦. 比如, 孤獨的你躺在床上夜不能寐. 於是乎, 拿出手機, 點亮了屏幕, 撥通 <code>10086/<code>, 中國移動就會隨機分配一個當前處於空閒的客服MM, 你可以和客服MM聊聊天, 問問她家住哪裡, 有沒有男朋友, 她的微信號, 她的手機號, 星座, 八字.......

在這個例子中, 中國移動就充當了反向代理的角色. 你只需要撥打 <code>10086/<code>. 至於會不會分配到 MM 會分配到哪個 MM 在接通之前你都是不知道的. 反向代理在互聯網中的使用主要是實現負載均衡. 當你訪問某個網站的時候, 反向代理服務器會從當前網站的所有服務器中選擇一個空閒的服務器為你響應. 用於均衡每臺服務器的負載率.

一文读懂并实操 Nginx 反向代理

修改 hosts 完成域名綁定

mac 用戶直接執行 <code>vim /private/etc/hosts/<code>在 hosts 文件最後添加一行:

<code>127.0.0.1 a.com/<code>

這一句是什麼意思呢? 就是告訴我們的電腦訪問 <code>a.com/<code>的時候, 無需請求 DNS, 直接指向我們本機.

ps: win 環境下, hosts 文件在 <code>C:\\Windows\\System32\\drivers\\etc/<code>文件夾下. 如果沒有權限修改, 把 hosts 文件先拷貝到別的位置, 通過編輯器打開並添加最後一行內容以後再剪切到原來的位置替換即可.

驗證: 打開命令行窗口執行 <code>ping a.com/<code>, 如果訪問的 ip 為 127.0.0.1 說明我們的域名綁定就完成啦 ^_^

Tips:可以微信搜索:Java後端,關注後加入咱們自己的交流群。

安裝 nginx

要做 NGINX 反向代理, 肯定要安裝 nginx, 本文安裝步驟示例環境為 mac, win 的小夥伴, 可以百度一下嗷, 這個東西大同小異.

  • 安裝 brew 命令, 執行<code>ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"/<code>

  • 安裝 nginx, 執行 <code>brew install nginx/<code>

  • 啟動 nginx <code>nginx/<code>, 如果報沒有權限, 執行<code>sudo nginx/<code>

nginx 啟動後, 瀏覽器打開 localhost:8080, 即可驗證. 出現以下界面說明安裝成功.

一文读懂并实操 Nginx 反向代理

nginx 配置初探

配置完 hosts 域名已經能夠成功綁定. 現在如果我們訪問 <code>a.com/<code>實際上是會訪問到我們的自己的電腦辣. 那還不抓緊試一下?

瀏覽器訪問 a.com

這是什麼鬼????

一文读懂并实操 Nginx 反向代理

為什麼會 無法訪問此網站呢? 我們下載安裝完 nginx 還沒有做任何配置. 接下來, 我們稍微配置一下就 OK:

  • 命令行切換到 nginx 配置目錄下<code>cd /usr/local/etc/nginx/servers/<code>

  • 創建並編輯配置文件<code>vim test.conf/<code>, 在配置文件中粘貼以下內容


<code>server {
# 監聽80端口號
listen 80;

# 監聽訪問的域名
server_name a.com;

# 根據訪問路徑配置
location / {
# 把請求轉發到 https://www.baidu.com
proxy_pass https://www.baidu.com;
}
}/<code>

  • 保存文件, 並執行<code>nginx -s reload/<code>重啟 nginx.

  • 回到瀏覽器, 打開 a.com 的頁籤, 強制刷新.

一文读懂并实操 Nginx 反向代理

恭喜你已經完成了第一個 nginx 配置.

創建跨域環境

通過一系列的折騰, 我們已經可以通過 nginx 將<code>a.com/<code>轉發到百度. 完成了第一步, 接下來我們創建跨域的 Case 並一步一步通過 nginx 配置實現跨域.

首先, 項目前後端添加 nginx 目錄, 用戶存放前後端代碼. 代碼結構如下圖所示.

一文读懂并实操 Nginx 反向代理

其次編寫前後端代碼:

前端代碼(<code>./fe/nginx/index.html/<code>):

<code>





<title>CORS 實現跨域/<title>


CORS 實現跨域





/<code>

編寫完前端代碼以後, 啟動前端 web 容器. <code>live-server ./fe/nginx/<code>

一文读懂并实操 Nginx 反向代理

命令行中出現了黃色警告, 通知我們 8080 端口已經被佔用, 這又是為什麼呢? 大家請思考一哈.

我們重新指定一個端口<code>live-server ./fe/nginx --port=9999/<code>哈哈, 換一個指令, 依舊是那麼順暢. ^_^

後端代碼:

<code>const http = require('http');

const PORT = 8888;


const server = http.createServer((request, response) => {
console.log(request.headers)
response.end("{name: 'quanquan', friend: 'guiling'}");
});


server.listen(PORT, => {
console.log('服務啟動成功, 正在監聽: ', PORT);
});/<code>

啟動後端服務 <code>node ./be/nginx/index.js/<code>

完善 nginx 配置

前後端代碼已經準備完成, 這一步我們就來點乾貨. 完成最後的配置.

  • 首先, 修改 nginx 配置, 把百度地址替換成本地的前端地址

<code>server {
# 監聽80端口號
listen 80;

# 監聽訪問的域名
server_name a.com;

# 根據訪問路徑配置
location / {
# 把請求轉發到 http://127.0.0.1:9999
proxy_pass http://127.0.0.1:9999;
}
}/<code>
  • 修改完成 nginx 配置文件以後, 切記執行 <code>nginx -s -reload /<code>重啟 nginx.

  • 訪問a.com

一文读懂并实操 Nginx 反向代理

熟悉的報錯又出現了...

  • 修改前端項目中的接口地址:xhr.open('GET', '/api/getFriend')

  • 修改 nginx 配置文件

<code>server {
# 監聽80端口號
listen 80;

# 監聽訪問的域名
server_name a.com;

# 根據訪問路徑配置
location / {
# 把請求轉發到 http://127.0.0.1:9999
proxy_pass http://127.0.0.1:9999;
}

# 監聽根目錄下的 /api 路徑
location /api/ {
# 把請求轉發到 http://127.0.0.1:8888
proxy_pass http://127.0.0.1:8888;
}
}/<code>

新加的對於 api 路徑的監聽的意思就是把關於後端 api 的請求轉發到後端項目上(哈哈, 當然這就是為啥好多後端接口都是要有 <code>/api/<code>開頭的啦). 重啟 nginx 以後, 再次刷新瀏覽器, 後端返回的結果已經成功的打印到了控制檯, 本次跨域訪問任務完成.

一文读懂并实操 Nginx 反向代理

細心的小夥伴肯定發現了, 控制檯還有一個報錯. 這個是因為我們的項目中用到了 <code>live-server/<code>這個工具需要 websocket 導致的. 我們可以通過添加以下配置解決.

<code>proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";/<code>
一文读懂并实操 Nginx 反向代理

報錯消失 , 此時完整的 nginx 配置文件為

<code>server {
# 監聽80端口號
listen 80;

# 監聽訪問的域名
server_name a.com;


# 根據訪問路徑配置
location / {
# 把請求轉發到 http://127.0.0.1:9999
proxy_pass http://127.0.0.1:9999;

# 兼容websocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

# 監聽根目錄下的 /api 路徑
location /api/ {
# 把請求轉發到 http://127.0.0.1:8888
proxy_pass http://localhost:8888;
}
}/<code>

前後端代碼地址為:

https://github.com/luoquanquan/cross-domain/commit/f38f56689fdac1526244ecadaa979a52c9c4a7ea

總結

至此, 我們已經通過 nginx 反向代理的方式實現了跨域訪問 api, 在系列文章第一篇對於跨域的解釋為: 跨域源於同源策略, 是瀏覽器保證用戶安全的行為. 我們使用的 nginx 反向代理實際上是對瀏覽器的一種 "哄騙", 讓它認為自己訪問到的是同域的 api. 實際上是在服務端做了個調包, 這個道理就如同你撥打 10086 你就認定了給你分配到的一定是中國移動的客服MM(客服GG也是有可能出現的 )而中國移動的客服MM就是一個很安全的聊天對象, 沒有必要再進行限制...

下集預告: 終於蹩腳的碼完了最後一行, 作為生產環境中最常用的 nginx 反向代理, 比我想象的要簡單很多很多. 由於涉及到諸多配置的步驟. 有寫的不明白的地方還望小夥伴們評論區一起討論. 下一節預計聊聊服務端代理 <code>ServerProxy/<code>這個也是我要做的接口測試工具需要用到的技術方案, See you.


分享到:


相關文章: