原文地址: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 服務器(在本例中,我們稱之為代理)和一個服務器。這個例子主要的場景是,服務器不知道哪個客戶端在請求(響應)。是不是有點難以理解?下面讓我用示意圖講解下:
如圖,client1 和 client2 通過代理服務器向服務器發送請求 request1 和 request2,此時后端服務器不知道 request1 是由 client1 發送的還是 client2 發送的,但會執行(響應)操作。
反向代理
簡單來說,反向代理與代理的功能相反。現在我們有一個客戶端、一個中間 Web 服務器和 N 個后端服務器(N >= 1),同樣的來看下示意圖:
如圖,客戶端將通過 Web 服務器發送請求。而 Web 服務器會通過一個算法,當中最有意思的算法是輪詢,直接將請求指向許多后端服務器中的一個,並通過 Web 服務器將響應返回給客戶端。因此,在上面的例子中,客戶端其實並不知道在與哪個后端服務器進行交互。
負載均衡
又是枯燥的一個名詞:負載均衡,不過它很好理解,因為負載均衡本身就是反向代理的一個實例。
來看看負載均衡和反向代理的本質區別。在負載均衡中,你必須有 2 個或者更多的后端服務器,但在反向代理中,多台服務器不是必需的,甚至一台后端服務器也能運作。我們再深入點,如果我們有很多來自客戶端的請求,負載均衡器會檢查每個后端服務器的狀態,均勻地分配請求,更快地向客戶端發送響應。
有狀態 vs 無狀態應用
Okay,在我們開始實踐 Nginx 之前,先搞清所有的基本知識!
有狀態應用
有狀態應用存了一個額外變量,只用來保存服務器中單個實例使用所需的信息。
如圖所示,一個后端服務器 server1 存儲了一些信息,服務器 server2 並不存儲此信息,因此,客戶端 (上圖 Bob) 的交互可能會也可能不會得到想要的結果,因為它可能會與 server1 或 server2 交互。在本例中,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 服務器再發送給客戶端。
如果我們使用一個諸如輪詢這樣的算法,它讓 client2 向 https://localhost
發送一個請求,然后 Nginx 服務器會先將請求傳到 3000 端口並將響應返回給客戶端。對另一個請求,Nginx 會把請求傳給 3002 端口,以此類推。
知識儲備完成!到這里,你對 Nginx 是什么以及 Nginx 所涉及的術語有了一個清晰的理解。是時候,了解安裝和配置技術了。
開始安裝 Nginx
時機到了,如果你了解了上面的概念,可以動手開始 Nginx 實踐了。
嗯,Nginx 的安裝過程對任何系統來說都很簡單。我是一個 Mac OSX 用戶,所以例子的命令是基於 macOS 的, Ubuntu、Windows 和其他 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-demo
和 temp-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
上面命令將打開一個空文件,我們將為它添加配置。
-
添加配置的基本設置。一定要添加
events {}
,因為在 Nginx 架構中,它通常用來表示 worker 的數量。在這里我們用http
告訴 Nginx 我們將在 OSI 模型 的第 7 層作業。這里,我們告訴 Nginx 監聽 5000 端口,並指向 main 文件夾中的靜態文件。
http { server { listen 5000; root /path/to/nginx-demo/main/; } } events {}
-
接下來我們將為
/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 根路徑,還可以設置規則,這樣我們就能阻止客戶端訪問某個文件了。
-
接下來,我們在主服務器上編寫一個規則來防止任意 .md 文件被訪問。我們可以在 Nginx 中使用正則表達式,因此我們將這樣定義規則:
location ~ .md { return 403; }
-
最后,讓我們學習下
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 命令
-
首次啟動 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 進程並殺死進程,然后重新啟動它們。
要殺死一個進程,你需要 PID,再用以下命令殺死它:
$ kill -9 <PID>
#OR
$ sudo kill -9 <PID>
結束本文之前,聲明下,文中我用了些來自 Google 的圖片和 Hussein Nasser 發布在油管的視頻教程。
下面盡情享受 Coding、探索 Nginx 的魔力吧!👋
最后,歡迎優秀的你加入 HelloGitHub 的「譯文亦舞」系列,讓你的才華舞動起來!把優秀的文章分享給更多的人。要求:
- 平時瀏覽 GitHub、開源、編程、程序員等英文資訊和文章
- 想把自己閱讀到優秀的英文文章分享給更多的人
- 翻譯准確但不是直翻或機翻
- 保證每月至少翻譯或校正 1 篇高質量文章
- 了解 Markdown 和排版規則
- 聯系微信:xueweihan (備注:翻譯)