歡迎光臨
每天分享高質量文章

NGINX 反向代理

來自:掘金,作者:圈圈的圈

鏈接:https://juejin.im/post/5c0e6d606fb9a049f66bf246

代理是個啥

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

 

正向代理

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

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

反向代理

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

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

修改 hosts 完成域名系結

mac 用戶直接執行 vim /private/etc/hosts 在 hosts 檔案最後添加一行:

127.0.0.1 a.com


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

ps: win 環境下, hosts 檔案在 C:WindowsSystem32driversetc 檔案夾下. 如果沒有權限修改, 把 hosts 檔案先拷貝到別的位置, 通過編輯器打開並添加最後一行內容以後再剪切到原來的位置替換即可.

驗證: 打開命令列視窗執行 ping a.com, 如果訪問的 ip 為 127.0.0.1 說明我們的域名系結就完成啦 ^_^

安裝 nginx

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

 

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

  • 安裝 nginx, 執行 brew install nginx

  • 啟動 nginx nginx, 如果報沒有權限, 執行 sudo nginx

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

nginx 配置初探

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

瀏覽器訪問 a.com

這是什麼鬼????

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

  • 命令列切換到 nginx 配置目錄下 cd /usr/local/etc/nginx/servers

  • 創建並編輯配置檔案 vim test.conf, 在配置檔案中粘貼以下內容

server {

      # 監聽80端口號

      listen 80;

      # 監聽訪問的域名

      server_name a.com;

      # 根據訪問路徑配置

      location / {

          # 把請求轉發到 https://www.baidu.com

          proxy_pass https://www.baidu.com;

      }

  }


  • 儲存檔案, 並執行 nginx -s reload 重啟 nginx.

  • 回到瀏覽器, 打開 a.com 的頁簽, 強制掃清.

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

創建跨域環境

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

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

其次編寫前後端代碼:

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

DOCTYPE html>

<html lang=“en”>

<head>

    <meta charset=“UTF-8”>

    <meta name=“viewport” content=“width=device-width, initial-scale=1.0”>

    <meta httpequiv=“X-UA-Compatible” content=“ie=edge”>

    <title>CORS 實現跨域title>

head>

<body>

    <h3>CORS 實現跨域h3>

    <script>

        var xhr = new XMLHttpRequest()

        xhr.open(‘GET’, ‘http://localhost:8888/api/getFriend’)

        xhr.setRequestHeader(‘token’, ‘quanquanbunengshuo’)

        xhr.withCredentials = true;

        xhr.onreadystatechange = function() {

            if(xhr.readyState === 4 && xhr.status === 200) {

                console.log(xhr.responseText)

                console.log(xhr.getAllResponseHeaders())

            }

        }

        xhr.send()

    script>

body>

html>


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

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

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

後端代碼:

const http = require(‘http’);

const PORT = 8888;

// 創建一個 http 服務

const server = http.createServer((request, response) => {

  console.log(request.essay-headers)

  response.end(“{name: ‘quanquan’, friend: ‘guiling’}”);

});

// 啟動服務, 監聽端口

server.listen(PORT, () => {

  console.log(‘服務啟動成功, 正在監聽: ‘, PORT);

});


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

完善 nginx 配置

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

 

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

server {

      # 監聽80端口號

      listen 80;

      # 監聽訪問的域名

      server_name a.com;

      # 根據訪問路徑配置

      location / {

          # 把請求轉發到 http://127.0.0.1:9999

          proxy_pass http://127.0.0.1:9999;

      }

  }


  • 修改完成 nginx 配置檔案以後, 切記執行 nginx -s -reload 重啟 nginx.

  • 訪問a.com

熟悉的報錯又出現了…

  • 修改前端專案中的接口地址

// 接口地址修改為當前域名下 /api 路勁下的 getFriend

    xhr.open(‘GET’, ‘/api/getFriend’)


  • 修改 nginx 配置檔案

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;

        }

    }


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

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

proxy_http_version 1.1;

proxy_set_essay-header Upgrade $http_upgrade;

proxy_set_essay-header Connection “upgrade”;


報錯消失 ?, 此時完整的 nginx 配置檔案為

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_essay-header Upgrade $http_upgrade;

        proxy_set_essay-header Connection “upgrade”;

    }

    # 監聽根目錄下的 /api 路徑

    location /api/ {

        # 把請求轉發到 http://127.0.0.1:8888

        proxy_pass http://localhost:8888;

    }

}


前後端代碼地址為:https://github.com/luoquanquan/cross-domain/commit/f38f56689fdac1526244ecadaa979a52c9c4a7ea

總結

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

赞(0)

分享創造快樂