Nginx 簡介
Nginx 是一個高效能的 HTTP 和反向代理 Web 伺服器,同時也提供了 IMAP/POP3/SMTP 服務。
前向代理作為客戶端的代理,服務端只知道代理的 IP 地址而不知道客戶端的 IP 地址。
Nginx 安裝
推薦使用 LNMP 一鍵安裝包,Ubuntu/CentOS 等各平臺都有提供,省去自己配置的過程。
如果需要單獨安裝 Nginx,可以去找各平臺的安裝包名稱。以 Ubuntu Desktop 19.04 為例,單獨安裝 Nginx 的命令如下:
sudo apt install nginx
Nginx 安裝後預設啟動,開啟瀏覽器輸入 http://127.0.0.1
檢查是否安裝成功。
練習 1
使用
tail -f /path/to/nginx/log/access.log
實時監控檔案變化,再分別本地訪問 127.0.01 和遠端訪問伺服器 IP 地址,比較兩次訪問的日誌有什麼不同?Tips: Ubuntu Server 版預設沒有桌面,通過 SSH 連線到伺服器
- 開啟新終端,通過 SSH 連線到伺服器,再使用 curl 127.0.0.1 命令返回頁面原始檔
- 開啟客戶端瀏覽器,輸入伺服器 IP 地址
- 比較上面兩步對應的操作日誌有什麼區別
剛才在 Ubuntu 預設的火狐瀏覽器開啟 127.0.0.1 時的訪問日誌如圖。
接下來換一臺電腦訪問 192.168.23.129。
首先可以看到,UA 是不一樣的,這是因為我用了不同的瀏覽器,當然,訪問時間等也是不一樣的。
最關鍵的一點,第一次訪問的 IP 是 127.0.0.1,是環回地址,而後一次訪問的 IP 是 192.168.23.1,這個是我 Windows 10 的 IP 地址。
最後看一點實戰的內容——我的部落格的訪問日誌:
從中可以看到類似的日誌記錄,不僅記錄了訪問者的 IP、UA,還記錄了訪問資源 URL 以及一些附加的資訊。
同樣的,還有錯誤日誌,例如看一下gitlab.error.log
。
有了這些日誌,管理員就方便排查問題了。Nginx 預設配置
配置檔案:/etc/nginx/nginx.conf
(如果是 LNMP 安裝的,則可能在/usr/local/nginx/conf/nginx.conf
)。
可以用less
檢視配置檔案,配置檔案預設的環境是全域性環境,即一個main{}
,後面會定義使用者、工作程式等,以及 HTTP 服務、郵件服務。
下面主要講一下 HTTP 配置檔案。
首先在HTTP{}
會有一些全域性的配置,包括訪問日誌、連線超時等資訊,隨後會給出一個或多個server
表示多個虛擬主機。
來看一下實戰的配置檔案。
使用者和使用者組都是 www,配置了錯誤日誌的訪問路徑,工作模式是 epoll、IO 多路複用,單個程式的最大連線數是 51200。
配置了 fastcgi 相關資訊。Nginx 作為 HTTP 伺服器的配置
Nginx 預設的靜態資原始檔夾為/var/www/html
(不同的安裝包可能有不同的預設路徑,例如可能為/usr/local/nginx/www/html/default
或者其他目錄,也可以自己指定)。
在預設目錄下,新建一個叫做jxtxzzw.html
的檔案,隨便寫一點東西。
然後在nginx.conf
的 HTTP 結點中新增一個虛擬伺服器,並sudo nginx -s reload
重新載入。
如圖,在 80 埠監聽,當使用者訪問的伺服器是jxtxzzwtest.com
的時候,就定位到/var/www/html/
下,並當使用者沒有指定訪問的路徑的時候,預設訪問jxtxzzw.html
。
為了模擬域名解析的過程,修改/etc/hosts
檔案,增加jxtxzzwtest.com
的 IP 為127.0.0.1
。
修改之後開啟瀏覽器訪問jxtxzzwtest.com
,可以看到剛才的頁面。
如何不購買新的二級域名和伺服器,利用該伺服器和已有的域名再做一個個人主頁呢?
這就可以新增一個新的虛擬伺服器。
重複上面的步驟,只是注意新增虛擬伺服器的時候取一個新的server_name
,例如new.jxtxzzwtest.com
,至於location
寫什麼,就看個人主頁放在了哪個資料夾下面了。這些都可以根據自己需要修改。隨後,在
server { listen 80; server_name new.jxtxzzwtest.com; location / { index a_new_page.html; root /home/jxtxzzw/web/; } }
hosts
模擬 DNS 解析,新增127.0.0.1 new.jxtxzzwtest.com
之後就可以在瀏覽器訪問new.jxtxzzwtest.com
來看到個人主頁了。練習 2
- 在配置檔案 nginx.conf 的 http 節點內新增一個虛擬伺服器,新建 /var/www/EXAMPLE.com 資料夾,該資料夾下新建 index.html 檔案寫入文字,重載入配置 sudo nginx -s reload (注:將本頁中的 EXAMPLE 替換成自己的名字拼音)
- 瀏覽器輸入 IP 地址,檢查是否生成 /var/log/nginx/EXAMPLE.access.log 檔案,同時檢查 /var/log/nginx/access.log 檔案是否有變化
- 修改自己客戶端電腦上的 hosts 檔案,新增兩行解析到伺服器 IP 地址
- 瀏覽器輸入 www.EXAMPLE.com,檢查是否生成 /var/log/nginx/EXAMPLE.access.log,同時監測 /var/log/nginx/access.log 和 /var/log/nginx/EXAMPLE.access.log 檔案的變化
server { listen 80; server_name www.zzw.com; access_log /var/log/nginx/zzw.access.log; location / { index index.html; root /var/www/html/zzw.com/; } }
輸入 IP 地址,不論是本機訪問 127.0.0.1 還是另一臺電腦訪問 192.168.23.129,發現都只訪問了 Nginx 預設的安裝成功頁面,沒有進入 zzw.com。
顯然的,只有 access.log 會有變化,記錄了本次訪問資訊。
而在新增了 hosts 以後,訪問 www.zzw.com 就會看到剛才輸入的資訊。
需要注意的是,在配置檔案中只定義了www.zzw.com
,沒有定義zzw.com
,所以,在訪問 zzw.com 的時候還是會跳轉到 Nginx 安裝成功的那個頁面。
解決這個辦法可以在server_name
後面增加一個別名。看到 zzw.access.log 和 access.log 都有了新的記錄。
server_name www.zzw.com zzw.com;
來看一些實戰的內容。
我的部落格,監聽了 80 埠,同時處理www.jxtxzzw.com
和jxtxzzw.com
兩個伺服器名字,並對 80 埠的請求全部轉發到 443 埠。
443 埠配置了一些關於 SSL 相關的資訊,並且匯入了 PHP 相關的配置。
同時,還有一個gitlab.jxtxzzw.com
的虛擬主機,這個配置檔案將在下面詳述。負載均衡簡介
負載均衡轉發演算法:
- 輪詢(Round Robin):為第一個請求選擇列表中的第一個伺服器,然後按順序向下移動列表直到結尾,然後迴圈
- 最小連線(Least Connection):優先選擇連線數最少的伺服器,在普遍會話較長的情況下推薦使用
- 雜湊(Hash):根據請求源的 IP 的雜湊來選擇要轉發的伺服器,這種方式可以一定程度上保證特定使用者能連結到相同的伺服器
負載均衡演算法:- round:每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器當機,能自動刪除
- weight:指定輪詢機率,weight 和訪問比率成正比,用於後端伺服器效能不均的情況
- fiar(第三方):按後端伺服器的響應時間來分配請求,響應時間短的優先分配
- ip_hash:每個請求按訪問 IP 的雜湊結果分配,每個訪客固定訪問一個後端伺服器,可以解決 session 的問題
- url_hash(第三方):每個請求按 URL 的雜湊結果分配,不同訪客訪問相同的伺服器
預備 Web 伺服器環境:
- 配置兩臺 Apache(httpd) 作為 Web 伺服器,例如可以使用 XAMPP
- XAMPP 的訪問日誌在
/opt/lampp/logs/access.log
- 一臺 Ubuntu Desktop 的虛擬機器,192.168.23.129,作為 Nginx 伺服器
- 一臺 Ubuntu Desktop 的虛擬機器,192.168.23.128,作為第 1 臺 XAMPP 伺服器
- 一臺 Ubuntu Server 的虛擬機器,192.168.23.130,作為第 2 臺 XAMPP 伺服器
- 一臺 Windows 的物理機,192.168.23.1,用來訪問
在 nginx.conf 的 http 節點下新增以下程式碼後重新載入配置修改電腦的 host 檔案,新增一個域名解析
upstream first { server 192.168.23.128; server 192.168.23.130; } server { listen 80; server_name load.jxtxzzwtest.com; location / { proxy_pass http://first; } }
192.168.23.129 load.jxtxzzwtest.com
瀏覽器訪問 load.jxtxzzwtest.com,發現開啟了 XAMPP 的一個介面,說明代理成功了。
但是到底訪問的是哪一個 XAMPP 呢?可以看一下日誌。
在此之前,重新整理幾次,看看日誌會不會訪問了不同的頁面。
日誌的觀察結果,可以看到 128 的那臺伺服器上收到了若干次來自 129 的轉發請求,而 130 的那臺伺服器上也收到了若干請求,但是觀察時間可以看到,兩臺伺服器上接受的請求是先後交替的,這意味著符合輪詢演算法的期望結果。
更加直觀的方法,是可以修改其中一個 Apache 伺服器的主頁顯示。
簡單粗暴的方法,刪掉了 128 那臺伺服器的 index.html。
然後重新整理頁面的效果就是交替出現 XAMPP 的 dashboard 和 Directory Listing。
重新整理以後變成下面這個頁面,兩個頁面在每次重新整理後交替顯示。
如果沒有交替顯示,有可能是瀏覽器做了快取,強制重新整理一下就好了。練習 3
在 nginx.conf 的 http 節點下新增 upstream second 方案,將 server 節點下的 proxy_pass 設為 second 後重載入配置,其中 IP 地址要換成自己伺服器的地址,瀏覽器訪問域名,監測 Nginx 伺服器的 /var/log/nginx/access.log 和兩臺 Web 伺服器的 /opt/lampp/logs/access.log 發現有什麼規律
upstream second { server 192.168.1.102:80; server 192.168.1.103 weight=3; }
新增 upstream third 方案,重複上述實驗
upstream third { ip_hash; server 192.168.1.102; server 192.168.1.103; }
訪問日誌可以看出,交替比例變為 3:1。
需要特別說明的是,瀏覽器可能存在快取,所以一定要去看日誌。
換成 hash 以後,我只能刷出 Index of /dashboard 這個頁面,不論重新整理多少次,而檢視訪問日誌也確實發現我被轉發到了 130 這個伺服器上。
換一臺裝置,可能(如果正好 hash 計算結果不同)就會被轉發到 128 的伺服器上。也可能還是訪問的 130 的伺服器。
再來看一些關於 Nginx 代理的實戰的例子。
第一個例子是 HTTPS 反向代理到 Docker,具體的配置過程可以看我的另一篇文章《Nginx代理HTTPS到Docker指定埠》(https://www.jxtxzzw.com/archives/4241),這裡只簡要的給出與反向代理、負載均衡相關的程式碼。
第二個例子是 GitLab。
如果不想用 GitLab 自帶的 Nginx 服務,而想要把 GitLab 作為一個虛擬主機統一在已有的 LNMP 服務中一起管理,可以用到反向代理。
由於 GitLab 預設的是在 socket 中通訊,所以有點不太一樣。
這兩張截圖省略了 GitLab 中與 SSL 配置相關的程式碼。練習 4
- 利用 XAMPP,搭建一個能訪問資料庫的動態網站,並通過負載均衡伺服器訪問
- 比較 Nginx 伺服器和 Apache 伺服器的異同
第一個練習,比較簡單,基本上只要復現本文內容即可,唯一的區別在於需要把本文中簡陋的 HTML 程式碼複雜化,加上與資料庫通訊的部分,例如,訪問資料庫並列出所有學生的姓名……
由於上一次練習《MySQL備份與主備配置》已經配置了雙主結構,所以,在一個 PHP 頁面中加入增刪改查的功能,並把頁面複製到另一臺伺服器上就可以了,訪問會通過負載均衡,資料庫的訪問會通過雙主備份,保證了資料的一致。
程式碼就不貼了。
另外,歡迎訪問我的個人部落格呀,https://www.jxtxzzw.com/。
第二個練習,簡單說一下。
Nginx 相對於 Apache 的優勢:
- Apache 是同步多程式模型,一個連線對應一個程式,Nginx 是非同步的,多個連線(萬級別)可以對應一個程式
- Nginx 的抗併發能力強很多,對資源需求更少
- Nginx 支援反向代理
- Nginx 支援 7 層負載均衡
Apache 相對 Nginx 的優點:- Rewrite,比 Nginx 的 Rewrite 強大
- 模組超多,基本想到的都可以找到
一般來說,需要效能的 Web 服務,用 Nginx,如果不需要效能只求穩定,那就 Apache 吧。總之,就是看自己需求的。
但是從個人使用經歷來看,我會推薦 Nginx 作為 Web 伺服器的首選。如果你是新手,什麼都沒接觸過,不妨先試試 Nginx?