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

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)

分享創造快樂