title: 【轉載】我希望多年前就知道的 Nginx 概念
date: 2021-08-14 09:32:45
comment: false
toc: true
category:
- 分享
tags: - 轉載
- nginx
- 概念
本文轉載自:[譯] 我希望多年前就知道的 Nginx 概念
- 原文地址:Nginx concepts I wish I knew years ago
- 原文作者:Aemie Jariwala
- 譯文出自:掘金翻譯計畫
- 本文永久鏈接:github.com/xitu/gold-m…
- 譯者:joyking7
- 校對者:PassionPenguin、ningzhy3
Nginx 是一個遵循主從架構的 Web 伺服器,可以用作反向代理、負載均衡器、郵件代理和 HTTP 快取。
哇!複雜的術語和混亂的定義,裡面充斥著大量令人困惑的詞語,對吧?不用擔心,我可以幫大家先了解 Nginx 的基本架構和術語,然後我們將安裝並創建 Nginx 配置。
為了讓事情變簡單,只需要記住:Nginx 是一個神奇的 Web 伺服器 。
簡單來說,Web 伺服器就像個中間人。比如你想訪問 dev.to,輸入地址 https://dev.to
,你的瀏覽器就會找出 https://dev.to
的 Web 伺服器地址,然後將其定向到後台伺服器,後台伺服器會把響應返回給客戶端。
代理 vs 反向代理#
Nginx 的基本功能是代理,所以現在就需要了解什麼是代理和反向代理。
代理#
好的,我們有一個或多個客戶端、一個中間 Web 伺服器(在這種情況下,我們稱它為代理)和一個伺服器。這其中最主要的事情是伺服器不知道哪個客戶端正在請求。是不是有點困惑?讓我用一張示意圖來解釋一下。
在這種情況下,客戶端 client1 和 client2 通過代理伺服器向伺服器發送請求 request1 和 request2,後台伺服器不會知道 request1 是由 client1 還是 client2 發送的,只會執行操作。
反向代理#
用最簡單的話說,反向代理就是把代理的工作反過來。比方說有一個客戶端、一個中間 Web 伺服器和一個或多個後台伺服器。讓我們繼續通過一張示意圖解釋吧!
在這種情況下,客戶端將通過 Web 伺服器發送一個請求,Web 伺服器會通過一種算法將請求定向到眾多伺服器的任意一個,其中一種算法是輪詢調度(Round-Robin)(最可愛的一個!),然後再將響應通過 Web 伺服器返回給客戶端。因此在這裡,客戶端並不知道與之互動的是哪一個後台伺服器。
負載均衡#
可惡,又是一個新詞,但是這個詞比較容易理解,因為它是反向代理 本身的一個實際應用。
我們先說說基本的區別。在負載均衡中,必須要有兩個或者更多的後台伺服器,但在反向代理設置中,這不是必須的,它甚至可以只跟單台後台伺服器一起使用。
讓我們從幕後看一下,如果我們有大量來自客戶端的請求,這個負載均衡器會檢查每個後台伺服器的狀態並分配請求的負載,然後將響應更快地發送給客戶端。
有狀態應用 vs 無狀態應用#
好的各位,我保證我很快就要講到 Nginx 代碼了,先讓我們把所有的基本概念搞清楚!
有狀態應用#
這個應用程序存儲了一個額外的變量,用於保存只適用於單個伺服器實例的信息。
我的意思是,如果後端伺服器 server1 存儲了一些信息,那麼它不會被存儲在 server2 上,因此進行互動的客戶端(這裡指 Bob)可能得不到想要的結果,因為它可能會與 server1 或者 server2 互動。在這種情況下,server1 將允許 Bob 查看配置文件,但 server2 不會允許。因此,即使有狀態應用阻止了許多 API 調用數據庫,並且速度更快,但卻可能會在不同伺服器上導致上述問題。
無狀態應用#
現在,無狀態是對數據庫的 API 調用更多,但客戶端與不同後台伺服器互動時,存在的問題就更少了。。
我知道你沒有明白我的意思。簡單來說,如果我從客戶端通過 Web 伺服器向比如說後台伺服器 server1 發送一個請求,它將向客戶端提供一個令牌以用於訪問其他任何請求。客戶端可以使用令牌並將請求發送給 Web 伺服器,該 Web 伺服器將請求和令牌一起發送給任意後台伺服器,每個伺服器都將返回相同的期望輸出。
什麼是 Nginx?#
Nginx 就是 Web 伺服器,到目前為止,我一直在整篇博客中使用 Web 伺服器這個詞,老實說,它就像一個中間人 。
這張圖並不難懂,它只是結合了我到現在為止解釋的所有概念。在這張圖中,我們有 3 台分別運行在 3001、3002、3003 端口的後台伺服器,這些後台伺服器共同使用運行在 5432 端口的數據庫。
現在,當客戶端向 https://localhost
(默認 443 端口)發送請求 GET /employees
時,Nginx 將根據算法把這個請求發送給任意一個後台伺服器,後台伺服器從數據庫中獲取信息,然後把 JSON 結果發送回 Nginx Web 伺服器,Nginx 再發送回客戶端。
如果我們要使用諸如輪詢調度 這樣的算法,Nginx 會這樣做:比如 client2 發送了一個請求到 https://localhost
,那麼 Nginx 伺服器會先把請求傳到 3001 端口,然後把響應返回給客戶端。對於另一個請求,Nginx 會把請求傳到 3002 端口,以此類推。
這也太多概念了吧!但是到此為止,你應該已經清楚地了解了什麼是 Nginx 及其相關術語。現在,我們將繼續了解 Nginx 的安裝和配置。
安裝過程#
終於到這一步了!如果你能理解 Nginx 概念並看到了代碼這部分,那真是棒棒哒!
好的,老實說,在任何操作系統上安裝 Nginx 都只需要一行命令。我是 Mac OSX 用戶,所以會基於它來寫命令。但對於 Ubuntu 和 Windows 以及其他 Linux 發行版,也有類似的命令。
brew install Nginx
只需要一行命令,你的系統就已經安裝上 Nginx 了!非常 Amazing!
運行 So easy!😛#
運行下面的命令來檢查 Nginx 是否在你的系統上運行起來了,又是非常簡單的一步。
nginx
# OR
sudo nginx
運行完命令之後,使用你最喜歡的瀏覽器訪問 http://localhost:8080/
,你將在屏幕上看到下面的畫面!
基本配置和示例#
好的,我們將通過一個示例來展示 Nginx 的神奇之處。首先,在本地機器上創建如下的目錄結構:
.
├── nginx-demo
│ ├── content
│ │ ├── first.txt
│ │ ├── index.html
│ │ └── index.md
│ └── main
│ └── index.html
└── temp-nginx
└── outsider
└── index.html
同時,在 html 和 md 文件中寫上基本的上下文內容。
我們要達到什麼效果?#
在這裡,我們有兩個單獨的文件夾 nginx-demo
和 temp-nginx
,每個文件夾都包含靜態 HTML 文件。我們將專注於在一個共同端口上運行這兩個文件夾,並設置我們喜歡的規則。
現在回到正軌。我們可以通過修改位於 /usr/local/etc/nginx
(譯者注:默認安裝路徑)路徑下的 nginx.conf
文件,實現對 Nginx 默認配置的任何改動。另外,我的系統中有 Vim,所以我將用 Vim 進行修改,你也可以自由使用所選的編輯器。
cd /usr/local/etc/nginx
vim nginx.conf
這將打開一個默認的 Nginx 配置文件,但我真的不想使用它的默認配置。因此,我通常會複製這個配置文件,然後對原文件進行修改。在這裡我們也這樣做。
cp nginx.conf copy-nginx.conf
rm nginx.conf && vim nginx.conf
現在打開一個空文件,我們將給它添加我們的配置。
-
添加一個基本配置。添加
events {}
是必須的,因為對於 Nginx 架構來講,它通常被用來表示 Worker 的數量。我們在這裡使用http
來告訴 Nginx,我們將使用 OSI 模型 的第 7 層。
在這裡,我們讓 Nginx 監聽 5000 端口,並指向/nginx-demo/main
文件夾下的靜態文件。http { server { listen 5000; root /path/to/nginx-demo/main/; } } events {}
-
接下來我們將對
/content
和/outsider
URL 添加額外的規則,其中 outsider 將指向第一步中提到的根目錄(/nginx-demo
)以外的目錄。
這裡location /content
表示無論我在子目錄中定義了哪一個根目錄,content 子 URL 都會被添加到定義的根目錄末尾。因此,這裡當我指定根目錄為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,還可以設置規則,以便於我可以阻止客戶端訪問某些文件。
-
我們將在定義的主伺服器中寫入一條附加規則,用來阻止訪問任何 .md 文件。我們可以在 Nginx 中使用正則表達式,規則定義如下:
location ~ .md { return 403; }
-
最後我們來學習一下流行的命令
proxy_pass
。現在我們已經了解了什麼是代理和反向代理,這裡我們先定義另一個運行在 8888 端口的後台伺服器,所以現在我們已經有了 2 個分別運行在 5000 和 8888 端口的後台伺服器。
我們要做的是,當客戶端通過 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 命令!#
-
首次啟動 Nginx Web 伺服器。
nginx #OR sudo nginx
-
重新加載正在運行的 Nginx Web 伺服器。
nginx -s reload #OR sudo nginx -s reload
-
關閉正在運行的 Nginx Web 伺服器。
nginx -s stop #OR sudo nginx -s stop
-
查找有哪些 Nginx 進程正在系統中運行
ps -ef | grep Nginx
第 4 條命令很重要,當前 3 條命令出現錯誤時,可以使用第 4 條命令找到所有正在運行的 Nginx 進程,然後 kill 掉這些進程,重新啟動 Nginx 服務。
要 kill 一個進程,你需要先知道它的 PID,然後用下面的命令 kill 它:
kill -9 <PID>
#OR
sudo kill -9 <PID>
在結束這篇文章之前,聲明一下我所使用圖片和視覺效果來自 Goole 圖片和由 Hussein Nasser 提供的 Youtube 教程。
關於 Nginx 的基本認識和配置,我們就講到這裡。如果你對 Nginx 的進階配置感興趣,請通過評論告訴我。在此之前,請享受編程的樂趣,探索 Nginx 的魔力!👋
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計畫 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。
掘金翻譯計畫 是一個翻譯優質互聯網技術文章的社區,來源文章為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計畫、官方微博、知乎專欄。