寫給小白的 Nginx 文章


原文地址:Nginx concepts I wish I knew years ago

原文作者:Aemie Jariwala(已授權)

譯者 & 校正:HelloGitHub-小魚干 & 鹵蛋

Nginx 是一個采用主從架構的 Web 服務器,可用於反向代理、負載均衡器、郵件代理和 HTTP 緩存

Emmm,上面的 Nginx 介紹看過去有些復雜而且充滿了不明覺厲的術語。Relax,在這篇文章里,我(原作者)會先帶你理解 Nginx 的架構和專有術語,最后實踐一把安裝和配置 Nginx

簡單來說,你只要記住一點:Nginx 是個神奇的 Web 服務器。(注:神奇之處下文會娓娓道來)

那什么是 Web 服務器呢?簡而言之,Web 服務器就是一個中間人。舉個例子,你要訪問 hellogithub.com(注:原文例子為 dev.to),在地址欄輸入 https://hellogithub.com 時,你的瀏覽器會找到 https://hellogithub.com 的網絡服務器地址並將它指向后端服務器,后端服務器再返回響應給客戶端。

代理 vs 反向代理

Nginx 的基本特性是代理,所以你一定要明白什么是代理反向代理

代理

看個小例子,現在我們有 N 個客戶端(N >= 1),一個中間 Web 服務器(在本例中,我們稱之為代理)和一個服務器。這個例子主要的場景是,服務器不知道哪個客戶端在請求(響應)。是不是有點難以理解?下面讓我用示意圖講解下:

如圖,client1client2 通過代理服務器向服務器發送請求 request1request2,此時后端服務器不知道 request1 是由 client1 發送的還是 client2 發送的,但會執行(響應)操作。

反向代理

簡單來說,反向代理與代理的功能相反。現在我們有一個客戶端、一個中間 Web 服務器和 N 個后端服務器(N >= 1),同樣的來看下示意圖:

如圖,客戶端將通過 Web 服務器發送請求。而 Web 服務器會通過一個算法,當中最有意思的算法是輪詢,直接將請求指向許多后端服務器中的一個,並通過 Web 服務器將響應返回給客戶端。因此,在上面的例子中,客戶端其實並不知道在與哪個后端服務器進行交互。

負載均衡

又是枯燥的一個名詞:負載均衡,不過它很好理解,因為負載均衡本身就是反向代理的一個實例。

來看看負載均衡和反向代理的本質區別。在負載均衡中,你必須有 2 個或者更多的后端服務器,但在反向代理中,多台服務器不是必需的,甚至一台后端服務器也能運作。我們再深入點,如果我們有很多來自客戶端的請求,負載均衡器會檢查每個后端服務器的狀態,均勻地分配請求,更快地向客戶端發送響應。

有狀態 vs 無狀態應用

Okay,在我們開始實踐 Nginx 之前,先搞清所有的基本知識!

有狀態應用

有狀態應用存了一個額外變量,只用來保存服務器中單個實例使用所需的信息。

如圖所示,一個后端服務器 server1 存儲了一些信息,服務器 server2 並不存儲此信息,因此,客戶端 (上圖 Bob) 的交互可能會也可能不會得到想要的結果,因為它可能會與 server1server2 交互。在本例中,server1 允許 Bob 查看數據文件,但 server2 不允許。因此,雖然有狀態應用避免對數據庫的多次 API 調用,並且(響應)速度更快,但它可能會在不同的服務器上導致這個(無法得到想要結果)問題。

無狀態應用

無狀態應用有更多的數據庫 API 調用,但當客戶端與不同后端服務器的交互時,無狀態應用卻存在更少的問題。

沒明白?簡單來說,如果我通過 Web 服務器從客戶端向后端服務器 server1 發送請求,它將向客戶端返回一個令牌,用於任何進一步的訪問請求。客戶端可以使用令牌並向 Web 服務器發送請求。此 Web 服務器將請求連同令牌一起發送到任意后端服務器,而每個后端服務器都能提供相同的所需結果。

Nginx 是什么?

Nginx 是網絡服務器,到目前為止,我的整個博客一直在用這個網絡服務器。老實說,Nginx 這就像個中間人

這個圖不難理解,它是目前為止所有概念的一個組合。在這里,我們有 3 個后端服務器運行在 3001、3002 和 3003 端口,這些后端服務器都能訪問同一個運行在 5432 端口的數據庫。

當一個客戶端向 https://localhost (默認端口 443)發起一個 GET /employees 請求時,Nginx 將基於算法向任意后端服務器發送請求,從數據庫獲取數據並將 JSON 數據返回 Nginx Web 服務器再發送給客戶端。

如果我們使用一個諸如輪詢這樣的算法,它讓 client2https://localhost 發送一個請求,然后 Nginx 服務器會先將請求傳到 3000 端口並將響應返回給客戶端。對另一個請求,Nginx 會把請求傳給 3002 端口,以此類推。

知識儲備完成!到這里,你對 Nginx 是什么以及 Nginx 所涉及的術語有了一個清晰的理解。是時候,了解安裝和配置技術了。

開始安裝 Nginx

時機到了,如果你了解了上面的概念,可以動手開始 Nginx 實踐了。

嗯,Nginx 的安裝過程對任何系統來說都很簡單。我是一個 Mac OSX 用戶,所以例子的命令是基於 macOS 的, UbuntuWindows 和其他 Linux 發行版操作和例子類似。

$ brew install Nginx

只要執行上面這步,你的系統就有 Nginx 了!是不是很神奇!

運行 Nginx 如此簡單 😛

要檢查 Nginx 是否運行也很簡單。

$ nginx 
# OR 
$ sudo nginx

執行上面指令,再打開瀏覽器並輸入 http://localhost:8080/ 回車查看下,你會看到以下畫面!

Nginx 基本配置 & 示例

下面,我們通過實操來感受下 Nginx 的魔力。

首先,在本地創建如下的目錄結構:

.
├── nginx-demo
│  ├── content
│  │  ├── first.txt
│  │  ├── index.html
│  │  └── index.md
│  └── main
│    └── index.html
└── temp-nginx
  └── outsider
    └── index.html

當然,.html.md 文件中要包含基本信息。

我們想要得到什么呢?

這里,我們有兩個單獨的文件夾 nginx-demotemp-nginx,每個文件夾都包含靜態 HTML 文件。我們將着力在一個公共端口上運行這兩個文件夾,並設置我們想要的規則。

回到之前說的,如果要修改 Nginx 默認配置,得修改 usr/local/etc/nginx 目錄下的 nginx.conf文件。我的系統中有 vim,所以在這里用 vim 來更改 Nginx 配置,你可以用自己的編輯器來修改配置。

$ cd /usr/local/etc/nginx
$ vim nginx.conf

上面的命令會打開一個 Nginx 默認配置文件,我真的不想直接使用默認配置。因此,我通常的做法是復制這個配置文件,然后對主文件進行更改。這里也不例外。

$ cp nginx.conf copy-nginx.conf
$ rm nginx.conf && vim nginx.conf 

上面命令將打開一個空文件,我們將為它添加配置。

  1. 添加配置的基本設置。一定要添加 events {},因為在 Nginx 架構中,它通常用來表示 worker 的數量。在這里我們用 http 告訴 Nginx 我們將在 OSI 模型 的第 7 層作業。

    這里,我們告訴 Nginx 監聽 5000 端口,並指向 main 文件夾中的靜態文件。

    http {
    
      server {
        listen 5000;
        root /path/to/nginx-demo/main/; 
        }
    
    }
    
    events {}
    
  2. 接下來我們將為 /content/outsider URL 添加其他的規則,其中 outsider 將指向第一步中提到的根目錄之外的目錄。

    這里的 location /content 表示無論我在葉(leaf)目錄中定義了什么根(root),content 子 URL 都會被添加到定義的根 URL 的末尾。因此,當我指定 root 為 root /path/to/nginx-demo/時,這僅僅意味着我告訴 Nginx 在 http://localhost:5000/path/to/nginx-demo/content/ 文件夾中顯示靜態文件的內容。

    http {
    
      server {
          listen 5000;
          root /path/to/nginx-demo/main/; 
    
          location /content {
              root /path/to/nginx-demo/;
          }   
    
          location /outsider {
              root /path/temp-nginx/;
          }
      }
    
    }
    
    events {}
    

    酷斃了!現在 Nginx 不僅能定義 URL 根路徑,還可以設置規則,這樣我們就能阻止客戶端訪問某個文件了。

  3. 接下來,我們在主服務器上編寫一個規則來防止任意 .md 文件被訪問。我們可以在 Nginx 中使用正則表達式,因此我們將這樣定義規則:

      location ~ .md {
            return 403;
      }
    
  4. 最后,讓我們學習下 proxy_pass 命令來結束這個章節。我們已經了解了什么是代理和反向代理,在這里我們從定義另一個運行在 8888 端口上的后端服務器開始。現在,我們在 5000 和 8888 端口上運行了 2 個后端服務器。

    我們要做的是,當客戶端通過 Nginx 訪問 8888 端口時,將這個請求傳到 5000 端口,並將響應返回給客戶端!

    server {
        listen 8888;
    
        location / {
            proxy_pass http://localhost:5000/;
        }
    
        location /new {
            proxy_pass http://localhost:5000/outsider/;
        }
    }
    

看下,這是所有的配置信息 😁

http {

    server {
        listen 5000;
        root /path/to/nginx-demo/main/; 

        location /content {
            root /path/to/nginx-demo/;
        }   

        location /outsider {
            root /path/temp-nginx/;
        }

                location ~ .md {
          return 403;
        }
    }

      server {
        listen 8888;

        location / {
            proxy_pass http://localhost:5000/;
        }

        location /new {
            proxy_pass http://localhost:5000/outsider/;
        }
  }

}

events {}

使用 sudo nginx 來運行此配置。

其他 Nginx 命令

  1. 首次啟動 Nginx Web 服務器。

    $ nginx 
    #OR 
    $ sudo nginx
    
  2. 重新加載正在運行的 Nginx Web 服務器。

    $ nginx -s reload
    #OR 
    $ sudo nginx -s reload
    
  3. 停止正在運行中的 Nginx Web 服務器。

    $ nginx -s stop
    #OR 
    $ sudo nginx -s stop
    
  4. 查看系統上運行的 Nginx 進程。

    $ ps -ef | grep Nginx
    

第 4 條命令很重要,如果前 3 條命令產生了一些問題,通常你可以用第 4 條命令找到所有正在運行的 Nginx 進程並殺死進程,然后重新啟動它們。

要殺死一個進程,你需要 PID,再用以下命令殺死它:

$ kill -9 <PID>
#OR 
$ sudo kill -9 <PID>

結束本文之前,聲明下,文中我用了些來自 Google 的圖片和 Hussein Nasser 發布在油管的視頻教程。

下面盡情享受 Coding、探索 Nginx 的魔力吧!👋

最后,歡迎優秀的你加入 HelloGitHub 的「譯文亦舞」系列,讓你的才華舞動起來!把優秀的文章分享給更多的人。要求:

  • 平時瀏覽 GitHub、開源、編程、程序員等英文資訊和文章
  • 想把自己閱讀到優秀的英文文章分享給更多的人
  • 翻譯准確但不是直翻或機翻
  • 保證每月至少翻譯或校正 1 篇高質量文章
  • 了解 Markdown 和排版規則
  • 聯系微信:xueweihan (備注:翻譯)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM