Nginx 簡單入門指北不指南

熊的貓發表於2023-02-24

前言

老大:CDN + Nginx 怎麼玩的你知道不?

我:此處省略一億個點 ... ☺

老大:簡單來說,前端專案透過打包構建工具生成的最終產物,會先上傳到【物件儲存】中(例如:阿里雲 OSS、騰訊雲 COS);【物件儲存】中的靜態資源透過接入 CDN 服務,再由 CDN 進行加速處理,然後分發到使用者客戶端;但最前置會有個 Nginx 服務,它配置反向代理指向 CDN 地址,然後 CDN 去【物件儲存】中拉資料

老大:這是最常用的,前端資源打包後 PUSH 到【物件儲存】時,就會去觸發重新整理 CDN

我:此處贊一手 ☺

於是痛定思痛,開始學習 Nginx 相關的內容,於是有了這篇文章.

Nginx 基礎內容

是什麼?

Nginx 是一個輕量級的 HTTP 伺服器,採用事件驅動、非同步非阻塞處理方式的伺服器,它具有極好的 IO 效能,常用於 HTTP伺服器(包含動靜分離)正向代理反向代理負載均衡 等等.

NginxNode.js 在很多方面是類似的,例如都是 HTTP 伺服器、事件驅動、非同步非阻塞等,且 Nginx 的擁有的功能,也可以使用 Node.js 去實現,但它們的使用場景是不同的,Nginx 擅長於底層伺服器端資源的處理(靜態資源處理轉發、反向代理,負載均衡等),Node.js 更擅長上層具體業務邏輯的處理.

下載和啟動

下載

可直接訪問 Nginx 官網 進行下載對應的壓縮包:

  • 方式一:可直接在主頁面的各種 主版本(mainline version)穩定版本(stable version) 進行下載

image.png

  • 方式二:可透過右側導航的 download 選項進行下載,一般下載 穩定版本

image.png

解壓

將對應的 .zip 壓縮檔案解壓並存放到合適的磁碟目錄即可.

啟動服務

進入到對應的 Nginx 目錄,雙擊執行 nginx.exe 或者在命令列中透過 start nginx 啟動服務,啟動後會有一閃而過的彈窗,這就代表啟動成功了,此時透過瀏覽器訪問 http://localhost:

image.png

.conf 配置檔案簡介

Nginx 的配置檔案位置為 /nginx-xxx/conf/nginx.conf ,可以檢視或新增和修改配置檔案:

image.png

image.png

配置檔案大致結構可以分為:

image.png

Nginx 實戰

Http 服務

這裡直接使用一個簡單的 vite-vue3 專案來演示 nginx 部署靜態資源的過程:

  • 準備一個 demo 專案,正常透過腳手架的 web 服務進行訪問,如下:

    image.png

  • demo 專案進行打包得到構建的產物 dist 目錄

    image.png

  • dist 目錄更名為 vite-vue3 並放在 D:\nginx-1.22.0\html 目錄下

    image.png

  • 修改 D:\nginx-1.22.0\conf\nginx.conf 配置檔案,對應配置如下,比較簡單:

    image.png

  • 透過訪問 http://localhost/vite-vue3/ 部署好的頁面,如下所示:

    image.png
    以上只是簡單的配置靜態資源服務,還可以自行設定快取、配置代理、配置多個 server 內容等等

正向代理

正向代理的代理物件是客戶端,正向代理就是代理伺服器替客戶端去訪問目標伺服器.

這裡舉一個簡單的 跨域 的例子,然後透過 nginx 去配置代理,解決對應的跨域問題.

  • 後端服務部分 基於 express 來啟動模擬一個業務處理伺服器,程式碼如下:

    const express = require('express');
    
    const app = express();
    
    app.get('/',(req, res,next)=>{
        res.end('<h1>hello world!!!</h1>');
    });
    
    app.get('/getBooks',(req, res,next)=>{
        setTimeout(()=>{
            const data = new Array(5).fill(1).map((v,i) => {
                return {id: i + 1, name: `test title ${i+1}`, price: i + 100 }
            });
            res.json(data);
        }, 2000);
    });
    
    app.listen(8009, (err) => {
        if(err) {
            console.log("server run with error!!");
            return
        }
        console.log("server is runing at:http://10.98.214.68:8009");
    });
  • 前端頁面部分 仍然使用上面的 vite-vue 專案,只不過會在 App.vue 元件的 onMounted 生命週期鉤子中透過 fectch 請求 http://10.98.214.68:8009/getBooks 介面,結果如預期發生跨域:

    image.png

  • 透過 nginx 配置代理並重新啟動,具體如下:

    // 方式一
    location /getBooks {
            proxy_buffer_size 64k;
            proxy_buffers  32 32k;
            proxy_busy_buffers_size 128k;
    
            add_header Access-Control-Allow-Origin '*' always;
            add_header Access-Control-Allow-Headers "Accept,Accept-Encoding,Accept-Language,Connection,Content-Length,Content-Type,Host,Origin,Referer,User-Agent";
            add_header Access-Control-Allow-Methods "GET, POST, PUT, OPTIONS";
            add_header Access-Control-Allow-Credentials true;
    
            proxy_pass  http://10.98.214.68:8009/getBooks;
    }
  • App.vue 中透過請求 nginx 代理伺服器,程式碼如下:

    onMounted(() => {
      console.log('傳送請求')
      fetch('http://10.98.214.68:80/getBooks')
        .then((res) => {
          return res.json()
        })
          .then((res) => {
          console.log('接收到響應結果:', res)
        })
        .catch((err) => {
          console.error('請求異常:', err)
        })
    })

    image.png

    反向代理

    反向代理指代理後端伺服器響應客戶端請求的一箇中介伺服器,代理的物件是服務端.

這裡舉一個透過頁面訪問 /abc//xyz/ 時,能夠分別訪問不同伺服器的例子,如下:

  • 啟動兩個 node 服務模擬不同的伺服器,如下:

     // server-abc.js
     const express = require('express');
     const app = express();
    
     app.get('/',(req, res,next)=>{
       res.end(`<h1>hello world 8001!!! <small>this page real url is http://127.0.0.1:8001</small></h1>`);
     });
    
     app.listen(8001, (err) => {
       if(err) {
           console.log("server run with error!!");
           return
       }
       console.log("server is runing at:http://127.0.0.1:8001");
     });
    
     // server-xyz.js
     const express = require('express');
     const app = express();
    
     app.get('/',(req, res,next)=>{
       res.end(`<h1>hello world 8002!!! <small>this page real url is http://127.0.0.1:8002</small></h1>`);
     });
    
     app.listen(8002, (err) => {
       if(err) {
           console.log("server run with error!!");
           return
       }
       console.log("server is runing at:http://127.0.0.1:8002");
     });

    image.png

    image.png

    • 配置 nginx 代理伺服器,實現透過訪問 /abc/ 能跳轉到 http://127.0.0.1:8001,透過訪問 /xyz/ 能跳轉到 http://127.0.0.1:8002,具體配置如下:
            location /abc/ {  
               proxy_pass http://127.0.0.1:8001/;         
            } 
    
            location /xyz/ {  
               proxy_pass http://127.0.0.1:8002/;         
            } 
    • 重啟 nginx 並訪問,如下:

      image.png

      image.png

負載均衡

負載均衡其意思就是分攤到多個操作單元上進行執行,例如 Web 伺服器、FTP 伺服器、企業關鍵應用伺服器和其它關鍵任務伺服器等,從而共同完成工作任務.

簡單說就是當有 2 臺或以上伺服器時,根據規則隨機的將請求分發到指定的伺服器上處理,負載均衡配置一般都需要同時配置反向代理,透過反向代理跳轉到負載均衡.

  • 核心配置如下:

    upstream myserver {   
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
    }
    
    server {
      listen       80;
      server_name  localhost;
      
      ...
    
      location / {
          root   html;
          index  index.html index.htm;
          proxy_set_header Host $host:$server_port;
          proxy_pass  http://myserver;  #請求轉向 myserver 定義的伺服器列表      
      }
      
      ...
     }

    最後

    以上就是本文的所有內容,有不當之處可以在評論區指出,希望本文對你有所幫助!

本文參與了SegmentFault 思否寫作挑戰賽,歡迎正在閱讀的你也加入。