1. Nginx簡介與核心架構
1.1 Nginx簡介
????????Nginx (engine x) 是一個高性能的 HTTP 和反向代理服務器,也是一個 IMAP/POP3/SMTP 郵件代理服務器。
????????由 Igor Sysoev 于2004年首次發布,其設計目標是解決 C10K 問題,即在一臺服務器上同時處理一萬個并發連接。
???????Nginx 以其高并發處理能力、低資源消耗和模塊化設計而聞名,廣泛應用于 Web 服務器、反向代理、負載均衡等場景。
1.1.1 主要特性
-
高并發處理能力:Nginx 使用異步、非阻塞事件驅動架構,能夠高效地處理大量并發連接。
-
低資源消耗:相對于傳統的進程或線程模型,Nginx 使用更少的內存和 CPU 資源。
-
模塊化設計:Nginx 的功能通過模塊實現,用戶可以根據需求加載不同的模塊。
-
高可擴展性:通過第三方模塊和 Lua 腳本,Nginx 能夠輕松擴展其功能。
-
豐富的功能:支持 HTTP/2、反向代理、負載均衡、緩存、SSL/TLS、WebSocket 等。
1.1.2 工作流程
-
當有新的 HTTP 請求到達時,master 進程會將其分發給一個工作進程。
-
工作進程處理請求,根據配置文件進行請求的處理,包括反向代理、負載均衡、靜態文件服務等。
-
處理完成后,工作進程將響應返回給客戶端。
1.1.3 工作模式
????????Nginx有兩種工作模式,分別為單進程工作模式和多進程工作模式。
????????單進程工作模式:除了一個主進程外,還有一個工作進行。這個工作進程是單線程的。默認的工作模式
????????多進程工作模式:除了一個主進程外,還有一個工作進行,每一個進程包含多個線程。
1.1.4 nginx目錄結構
????????安裝完Nginx后,我們先來熟悉一下Nginx的目錄結構,重點目錄/文件如下:
- conf/nginx.conf ---- nginx配置文件
- html ---- 存放靜態文件 (html、CSS、Js等)
- logs ---- 日志目錄,存放日志文件
- sbin/nginx ---- 二進制文件,用于啟動、停止Nginx服務
1.1.5 nginx常用命令
1. ./nginx -t #檢查配置文件的語法的正確性,并嘗試打開配置文件中所引用到的文件。
2. ./nginx -c /home/xx/nginx.conf #指定一個配置文件,來代替缺省的。
3. ./nginx -v #nginx 的版本。
4. ./nginx -s reload #reload 會重新加載配置文件,Nginx服務不會中斷。而且reload時會測試conf語法等。
5. ./nginx #啟動nginx。
6. ./nginx -s stop #stop 會立即停止服務,這種方法比較強硬,無論進程是否在工作,都直接停止進程。
7. ./nginx -s quit #quit 較stop相比就比較溫和一些了,需要進程完成當前工作后再停止。
1.2 核心架構
????????Nginx 的核心架構設計是其高性能和高可用性的關鍵。核心架構包括模塊化設計、事件驅動模型、Master-Worker 進程模型和高效的請求處理流程。
1.2.1 模塊化設計
????????Nginx 采用模塊化設計,核心功能和擴展功能都通過模塊實現。模塊分為核心模塊、標準 HTTP 模塊和第三方模塊。用戶可以根據需要啟用或禁用模塊,靈活配置 Nginx 的功能。
? ? ? ? nginx從功能上分為如下四類:
**Core(核心模塊):**構建nginx基礎服務、管理其他模塊。**Handlers(處理器模塊):**此類模塊直接處理請求,主要負責處理客戶端請求并產生待響應內容。**Filters (過濾器模塊):**此類模塊主要對其他處理器模塊輸出的內容進行修改。**Upstraem (反代理類模塊):**此類模塊是實現反向代理的功能。
**load-balancer(負載均衡模塊)😗*實現特定的算法,從服務器中選擇一個合適的服務器進行相應請求
各模塊之間的http處理流程:
1)客戶端發送HTTP請求
2) Nginx從配置文件選擇一個合適的模塊 , (如果有)負載均衡模塊就根據相應的算法選擇一個合適的服務器
3)處理模塊對客戶端的請求進行處理,并把輸出緩沖放到第一個過濾模塊上
4) 第一個過濾模塊處理后輸出給第二個過濾模塊,依此類推
5) 最后把響應發給客戶端。
-
核心模塊:包括 HTTP 模塊、事件模塊、解析器模塊等。實現 Nginx 的基本功能,如事件處理、內存管理、配置解析等。
-
Nginx 的 worker 進程分為核心模塊和功能性模塊。
-
核心模塊主要負責維持一個運行循環(run-loop),在其中執行網絡請求處理的不同階段的模塊功能,如網絡讀寫、存儲讀寫、內容傳輸、外出過濾,以及將請求發往上游服務器等。
-
HTTP 模塊處理 HTTP 請求和響應,包括 HTTP 頭部解析、HTTP 請求方法解析、URI 解析等。
-
事件模塊負責處理底層的事件通知機制,如 Epoll、Kqueue 等。
-
解析器模塊負責解析 Nginx 配置文件。
-
-
-
-
Nginx 的代碼采用了模塊化設計,這使得我們可以根據需要選擇和修改功能模塊,然后編譯成具有特定功能的服務器。
-
-
標準 HTTP 模塊:提供 HTTP 服務的功能,如靜態文件服務、反向代理、負載均衡等。
-
第三方模塊:由社區或開發者提供,擴展 Nginx 的功能,如 Lua 模塊、Redis 模塊等。
# 配置示例:啟用和配置 HTTP 模塊
http {server {listen 80;server_name example.com;location / {root /var/www/html;index index.html index.htm;}location /proxy {proxy_pass http://backend_server;}}
}
1.2.2 事件驅動模型
????????Nginx 使用異步、非阻塞事件驅動模型,能夠高效地處理并發連接。基于異步及非阻塞的事件驅動模型是Nginx 實現高并發、高性能的關鍵。
????????事件驅動模型基于 epoll(Linux)、kqueue(FreeBSD)等高效的 I/O 多路復用機制,實現事件的高效分發和處理。????????
????????這種模型使得 Nginx 能夠高效地處理大量并發請求,而不會因為阻塞等待而降低性能。
-
異步非阻塞:所有 I/O 操作都通過事件通知機制完成,不會阻塞進程。
-
Nginx 采用了事件驅動的模型,主要利用了操作系統提供的異步 I/O 機制。
-
當有新的連接建立或者數據可讀寫時,Nginx 不會阻塞等待,而是通過事件通知機制處理這些事件,從而提高了處理效率。
-
-
高效的事件分發:通過 epoll、kqueue 等機制,Nginx 能夠快速分發和處理大量并發連接的事件。
// 示例:基于 epoll 的事件循環
for (;;) {int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);for (int i = 0; i < n; i++) {if (events[i].events & EPOLLIN) {// 處理讀事件} else if (events[i].events & EPOLLOUT) {// 處理寫事件}}
}
1.2.3 Master-Worker 進程模型
????????Nginx 采用 Master-Worker 進程模型,確保高并發處理能力和高可靠性。Master 進程負責管理 Worker 進程,處理信號和管理共享資源。Worker 進程處理實際的請求,互不干擾,提高了并發處理能力和穩定性。
-
Master 進程:啟動、停止 Worker 進程,處理信號(如重新加載配置),管理共享資源(如緩存)。
-
Worker 進程:處理客戶端請求,每個 Worker 進程獨立處理不同的連接,避免相互影響。
# 配置示例:設置 Worker 進程數量
worker_processes auto;events {worker_connections 1024;
}
1.2.4 請求處理流程
????????Nginx 的請求處理流程高度優化,能夠高效地處理 HTTP 請求。主要流程包括接收請求、解析請求、選擇處理模塊、生成響應和發送響應。
-
接收請求:通過事件驅動模型接收客戶端請求。
-
解析請求:解析 HTTP 請求頭,生成請求上下文。
-
選擇處理模塊:根據配置選擇相應的模塊處理請求,如靜態文件服務、反向代理等。
-
生成響應:調用處理模塊生成響應數據。
-
發送響應:通過事件驅動模型發送響應給客戶端。
# 配置示例:靜態文件服務和反向代理
http {server {listen 80;server_name example.com;location / {root /var/www/html;index index.html index.htm;}location /proxy {proxy_pass http://backend_server;}}
}
1.3 Nginx配置文件結構
... #全局塊events { #events塊...
}http #http塊
{... #http全局塊server #server塊{ ... #server全局塊location [PATTERN] #location塊{...}location [PATTERN] {...}}server{...}... #http全局塊
}
????????1、全局塊:配置影響nginx全局的指令。一般有運行nginx服務器的用戶組,nginx進程pid存放路徑,日志存放路徑,配置文件引入,允許生成worker process數等。
????????2、events塊:配置影響nginx服務器或與用戶的網絡連接。有每個進程的最大連接數,選取哪種事件驅動模型處理連接請求,是否允許同時接受多個網路連接,開啟多個網絡連接序列化等。
????????3、http塊:可以嵌套多個server,配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置。如文件引入,mime-type定義,日志自定義,是否使用sendfile傳輸文件,連接超時時間,單連接請求數等。
????????4、server塊:配置虛擬主機的相關參數,一個http中可以有多個server。
????????5、location塊:配置請求的路由,以及各種頁面的處理情況。
示例:
########### 每個指令必須有分號結束。#################
#user administrator administrators; #配置用戶或者組,默認為nobody nobody。
#worker_processes 2; #允許生成的進程數,默認為1
#pid /nginx/pid/nginx.pid; #指定nginx進程運行文件存放地址
error_log log/error.log debug; #制定日志路徑,級別。這個設置可以放入全局塊,http塊,server塊,級別以此為:debug|info|notice|warn|error|crit|alert|emerg
events {accept_mutex on; #設置網路連接序列化,防止驚群現象發生,默認為onmulti_accept on; #設置一個進程是否同時接受多個網絡連接,默認為off#use epoll; #事件驅動模型,select|poll|kqueue|epoll|resig|/dev/poll|eventportworker_connections 1024; #最大連接數,默認為512
}
http {include mime.types; #文件擴展名與文件類型映射表default_type application/octet-stream; #默認文件類型,默認為text/plain#access_log off; #取消服務日志 log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定義格式access_log log/access.log myFormat; #combined為日志格式的默認值sendfile on; #允許sendfile方式傳輸文件,默認為off,可以在http塊,server塊,location塊。sendfile_max_chunk 100k; #每個進程每次調用傳輸數量不能大于設定的值,默認為0,即不設上限。keepalive_timeout 65; #連接超時時間,默認為75s,可以在http,server,location塊。upstream mysvr { server 127.0.0.1:7878;server 192.168.10.121:3333 backup; #熱備}error_page 404 https://www.baidu.com; #錯誤頁server {keepalive_requests 120; #單連接請求上限次數。listen 4545; #監聽端口server_name 127.0.0.1; #監聽地址 location ~*^.+$ { #請求的url過濾,正則匹配,~為區分大小寫,~*為不區分大小寫。#root path; #根目錄#index vv.txt; #設置默認頁proxy_pass http://mysvr; #請求轉向mysvr 定義的服務器列表deny 127.0.0.1; #拒絕的ipallow 172.18.5.54; #允許的ip } }
}需要注意的有以下幾點:1、1.$remote_addr 與$http_x_forwarded_for 用以記錄客戶端的ip地址; 2.$remote_user :用來記錄客戶端用戶名稱; 3.$time_local : 用來記錄訪問時間與時區;4.$request : 用來記錄請求的url與http協議;5.$status : 用來記錄請求狀態;成功是200, 6.$body_bytes_s ent :記錄發送給客戶端文件主體內容大小;7.$http_referer :用來記錄從那個頁面鏈接訪問過來的; 8.$http_user_agent :記錄客戶端瀏覽器的相關信息;2、驚群現象:一個網路連接到來,多個睡眠的進程被同事叫醒,但只有一個進程能獲得鏈接,這樣會影響系統性能。3、每個指令必須有分號結束。
1.3.1、localtion 路由匹配規則
????????什么是location? :?nginx根據用戶請求的URI來匹配對應的location模塊,匹配到哪個location,請求將被哪個location塊中的配置項所處理。
????????location配置語法:location [修飾符] pattern {…}
常見匹配規則如下:
修飾符 | 作用 |
---|---|
空 | 無修飾符的前綴匹配,匹配前綴是 你配置的(比如說你配的是 /aaa) 的url |
= | 精確匹配 |
~ | 正則表達式模式匹配,區分大小寫 |
~* | 正則表達式模式匹配,不區分大小寫 |
^~ | ^~類型的前綴匹配,類似于無修飾符前綴匹配,不同的是,如果匹配到了,那么就停止后續匹配 |
/ | 通用匹配,任何請求都會匹配到(只要你域名對,所有請求通吃!) |
1.3.2、前綴匹配(無修飾符)
首先我提前創建了prefix_match.html文件,之后改一下nginx.conf文件(給前綴是 /prefixmatch 的請求返回 /etc/nginx/locatest/prefix_match.html 這個文件) ,如下:
image.png
然后在宿主機hosts中配置域名 172.30.128.65?http://www.locatest.com?映射后,觀察到nginx服務器返回內容如下:
image.png
curl http://www.locatest.com/prefixmatch ? 301
curl http://www.locatest.com/prefixmatch? ? 301
curl http://www.locatest.com/PREFIXMATCH ? 404
curl http://www.locatest.com/prefixmatch/ ? 200
curl http://www.locatest.com/prefixmatchmmm ? 404
curl http://www.locatest.com/prefixmatch/mmm ? 404
curl http://www.locatest.com/aaa/prefixmatch/? 404
可以看到?域名/prefixmatch
?和域名/prefixmatch?
?返回了301 ,原因在于prefixmatch映射的 /etc/nginx/locatest/ 是個目錄,而不是個文件所以nginx提示我們301,這個我們不用管沒關系,總之我們知道:域名/prefixmatch
,域名/prefixmatch?
?和域名/prefixmatch/
?這三個url通過我們配置的?無修飾符前綴匹配規則?都能匹配上就行了。
ps:為了方便,我們下邊的幾個location規則演示不再跳轉靜態文件了,而是直接return一句話。
1.3.3、精確匹配( = )
為了演示精確匹配,我們再給nginx.conf文件增加一個location配置,如下標紅處:
image.png
實際效果如下:
image.png
http://www.locatest.com/exactmatch ? 200
http://www.locatest.com/exactmatch? ? 200
http://www.locatest.com/exactmatch/ ? 404
http://www.locatest.com/exactmatchmmmm ? 404
http://www.locatest.com/EXACTMATCH ? 404
可以看出來精確匹配就是精確匹配,差一個字也不行!
1.3.4、前綴匹配( ^~ )
我們上邊說了不帶任何修飾符的前綴匹配(5.1小節),這里我們看下 修飾符是 ^~的 前綴匹配和不帶修飾符的前綴匹配有啥區別,先在ngnx.conf文件增加個location并配好如下:
image.png
curl效果如下:
image.png
curl http://www.locatest.com/exactprefixmatch ? 200
curl http://www.locatest.com/exactprefixmatch/ ? 200
curl http://www.locatest.com/exactprefixmatch? ? 200
curl http://www.locatest.com/exactprefixmatchmmm ? 200
curl http://www.locatest.com/exactprefixmatch/mmm ? 200
curl http://www.locatest.com/aaa/exactprefixmatch ? 404
curl http://www.locatest.com/EXACTPREFIXMATCH ? 404
可以看到帶修飾符(^~
)的前綴匹配 像:域名/exactprefixmatchmmm
?和域名/exactprefixmatch/mmm
?是可以匹配上的,而不帶修飾符的前綴匹配這兩個類型的url是匹配不上的直接返回了404 ,其他的和不帶修飾符的前綴匹配似乎都差不多。
1.3.5、正則匹配(~ 區分大小寫)
ps:正則表達式的匹配,需要你對正則語法比較熟悉,熟悉語法后寫匹配規則也就得心應手了。
添加個location并配置,如下:( ^表示開頭,$表示結尾)
image.png
實際效果如下:
image.png
curl http://www.locatest.com/regexmatch ? 200
curl http://www.locatest.com/regexmatch/ ? 404
curl http://www.locatest.com/regexmatch? ? 200
curl http://www.locatest.com/regexmatchmmm ? 404
curl http://www.locatest.com/regexmatch/mmm ? 404
curl http://www.locatest.com/REGEXMATCH ? 404
curl http://www.locatest.com/aaa/regexmatch ? 404
curl http://www.locatest.com/bbbregexmatch ? 404
可以看到~修飾的正則是區分大小寫的。接下來我們看下 不區分大小寫的匹配。
1.3.6、正則匹配(~* 不區分大小寫)
改下location 在修飾符~后加個
image.png
看下實際效果:
image.png
可以看到這次 curl?http://www.locatest.com/REGEXMATCH?是可以匹配上的,說明 ~?確實是不區分大小寫的。
1.3.7、通用匹配( / )
通用匹配使用一個 / 表示,可以匹配所有請求,一般nginx配置文件最后都會有一個通用匹配規則,當其他匹配規則均失效時,請求會被路由給通用匹配規則處理,如果沒有配置通用匹配,并且其他所有匹配規則均失效時,nginx會返回404錯誤。
image.png
通用匹配實際效果:
image.png
可以看到通用匹配很好理解,只要你域名寫對了,那么所有的url都會被匹配上,來者不拒的感覺。
1.3.8、關于location 匹配優先級
上邊我們說了6種location匹配規則,那么如果存在多個到底走哪個location呢?這就的說說location的匹配優先級了。先來看下nginx官網和stackoverflow上的資料如下:
image.png
image.png
綜上資料我們對location匹配優先級的總結如下:?1. 優先走精確匹配
,精確匹配命中時,直接走對應的location,停止之后的匹配動作。 2.?無修飾符類型的前綴匹配
和?^~ 類型的前綴匹配
命中時,收集命中的匹配,對比出最長的那一條并存起來(最長指的是與請求url匹配度最高的那個location)。 3.?如果
步驟2中最長的那一條匹配是^~類型的前綴匹配
,直接走此條匹配對應的location并停止
后續匹配動作;如果步驟2最長的那一條匹配
不是^~類型的前綴匹配(也就是無修飾符的前綴匹配
),則繼續往下
匹配 5. 按location的聲明順序,執行正則匹配,當找到第一個命中的正則location時,停止后續匹配。 6. 都沒匹配到,走通用匹配( / )(如果有配置的話),如果沒配置通用匹配的話,上邊也都沒匹配上,到這里就是404了。
如果非要給修飾符排個序的話就是醬樣子:?=
?>?^~
?>?正則
?>?無修飾符的前綴匹配
?>?/
ok關于location就到這里,location是一個很重要的點,學好這個才知道nginx到底是咋匹配url的。
2. Nginx反向代理與負載均衡
????????Nginx 作為高性能的代理服務器,其代理原理是其設計的核心之一。無論是針對 HTTP 還是其他協議(如 FastCGI、Memcache、Redis 等)的網絡請求或響應,Nginx 都采用了代理機制來實現數據的轉發和處理。
????????Nginx 的代理原理主要基于以下幾個關鍵點:
????????接收請求:當 Nginx 接收到客戶端的請求時,根據配置文件中的代理設置,確定是否需要進行代理轉發。如果需要代理轉發,則根據配置選擇合適的代理方式。
????????建立連接:Nginx 會與目標服務器建立連接,可以是與遠程服務器建立 TCP 連接,也可以是與本地應用程序之間建立的 Unix Socket 連接,取決于代理目標的具體情況。
????????數據傳輸:一旦連接建立成功,Nginx 會將客戶端的請求數據轉發給目標服務器,并且在接收到目標服務器的響應后,再將響應數據返回給客戶端。這個過程可以是全雙工的,意味著 Nginx 可以同時接收客戶端請求和目標服務器響應,然后進行相應的轉發和處理。
????????代理緩存:為了進一步提高性能,Nginx 還支持代理緩存功能。它可以將經常請求的數據緩存在本地,避免每次請求都要向后端服務器發起請求,從而減少響應時間和網絡負載。
????????負載均衡:對于需要代理轉發的請求,Nginx 還支持負載均衡功能,可以根據一定的策略將請求分發到多個后端服務器上,以實現負載均衡和高可用性。
2.1 反向代理基礎
????????反向代理服務器在客戶端和服務器之間充當中介,接收客戶端的請求并將其轉發給后端服務器,然后將后端服務器的響應返回給客戶端。Nginx 作為反向代理服務器的優勢在于其高并發處理能力、靈活的配置和豐富的功能。
2.1.1 反向代理的優勢
-
隱藏后端服務器:反向代理隱藏了后端服務器的真實 IP 和端口,提升了安全性。
-
負載均衡:反向代理可以將請求分發到多臺后端服務器,實現負載均衡。
-
緩存:反向代理服務器可以緩存后端服務器的響應,減少后端服務器的壓力,提高響應速度。
-
SSL 終止:反向代理服務器可以處理 SSL/TLS 加密,減輕后端服務器的負擔。
2.1.2 反向代理配置示例
http {upstream backend {server backend1.example.com;server backend2.example.com;}server {listen 80;server_name example.com;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}
}下面是一個整體的參考:nginx 配置反向代理轉發proxy_pass#=======================================location 帶/結尾=======================================
# 請求url http://127.0.0.1:8080/proxy/index.html
location /proxy/ {proxy_pass http://127.0.0.1:8080/;
}
# 代理地址以 "/" 結尾,代理轉發的url地址為:http://127.0.0.1:8080/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080;
}
# 代理地址不以 "/" 結尾,代理轉發的url地址為:http://127.0.0.1:8080/proxy/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080/tomcat/;
}
# 代理地址以 "tomcat/" 結尾,代理轉發的url地址為:http://127.0.0.1:8080/tomat/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080/tomcat;
}
# 代理地址以 "tomcat" 代理轉發的url地址為:http://127.0.0.1:8080/proxytomcat/index.html#=======================================location 不帶/結尾=======================================
location /proxy {proxy_pass http://127.0.0.1:8080/tomcat;
}
# 代理地址以 "tomcat" 代理轉發的url地址為:http://127.0.0.1:8080/tomcat/index.htmllocation /proxy {proxy_pass http://127.0.0.1:8080/;
}
# 代理地址以 "/" 代理轉發的url地址為:http://127.0.0.1:8080//index.htmllocation /proxy {proxy_pass http://127.0.0.1:8080;
}
# 代理地址不以 "/" 代理轉發的url地址為:http://127.0.0.1:8080/proxy/index.html#=======================================alias與root=======================================
location /test/ {alias /www/abc/;
}
# 使用alias,當訪問/test/時,會到/www/abc/目錄下找文件location /test/ {root /www/abc;
}
# 使用root,當訪問/test/時,會到/www/abc/test/目錄下找文件(如果沒有test目錄會報403)#================================多層nginx代理@Websocket服務=======================================
location /secure/socket {add_header backendIP $upstream_addr;add_header backendCode $upstream_status;proxy_redirect off;proxy_connect_timeout 6000;proxy_read_timeout 6000; proxy_send_timeout 6000;proxy_set_header Host 192.168.9.101:8087;proxy_pass http://localhost:8080/websocket/web;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade"; proxy_set_header token $arg_username;
}
#================================多層nginx代理@Java服務=======================================
#主機127.0.0.1下的nginx配置,port=8081
location /local/app/ {proxy_pass http://10.9.103.36:8081/;
}
#主機10.9.103.36下的nginx配置,port=8081
location /chat/ {proxy_pass http://10.186.253.117:8081/;
}
#================================多層nginx代理@HTML資源=======================================
#主機10.9.103.35下的nginx配置,port=8083
location ^~ /html/chat/ {#符號^~:一旦匹配到,就不繼續匹配(靜態資源匹配)proxy_pass http://10.9.103.36:8081/;
}#主機10.9.103.36下的nginx配置,port=8081(下圖為html資源目錄結構)
location /mystatic {root html;index index.html index.htm;
}
2.2 負載均衡策略
????????Nginx 支持多種負載均衡策略,能夠根據不同的需求選擇合適的策略將請求分發到后端服務器。
名稱 | 說明 |
---|---|
輪詢 | 默認方式 |
weight | 權重方式 |
ip_hash | 依據ip分配方式 |
least conn | 依據最少連接方式 |
url hash | 依據url分配方式 |
fair | 依據響應時間方式 |
2.2.1 輪詢 (Round Robin)
????????輪詢是 Nginx 的默認負載均衡策略,將請求依次分發到每臺后端服務器。該策略簡單高效,適用于后端服務器性能均衡的情況。
upstream backend {server backend1.example.com;server backend2.example.com;
}
2.2.2 最少連接 (Least Connections)
????????最少連接策略將請求分發到當前活動連接數最少的服務器,適用于后端服務器性能不均衡的情況。
upstream backend {least_conn;server backend1.example.com;server backend2.example.com;
}
2.2.3 IP 哈希 (IP Hash)
????????IP 哈希策略根據客戶端 IP 計算哈希值,將同一客戶端的請求分發到同一臺服務器,適用于需要會話保持的場景。
upstream backend {ip_hash;server backend1.example.com;server backend2.example.com;
}
2.2.4 權重 (Weight)
????????權重策略為每臺服務器設置權重,權重越高,服務器接收到的請求越多,適用于后端服務器性能不均衡且需要手動調整分配比例的情況。
upstream backend {server backend1.example.com weight=3;server backend2.example.com weight=1;
}
2.3 配置實例
????????下面提供幾個反向代理和負載均衡的實際配置示例,以幫助理解和應用這些概念。
2.3.1 基本反向代理配置
server {listen 80;server_name example.com;location / {proxy_pass http://backend1.example.com;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.3.2 動靜分離配置
????????動靜分離是指將動態請求和靜態請求分別處理,以提高效率。Nginx 可以將靜態文件請求直接由 Nginx 處理,而將動態請求轉發給后端服務器。
server {listen 80;server_name example.com;location / {proxy_pass http://backend1.example.com;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}location /static/ {root /var/www/html;expires 30d;}
}
2.3.3 負載均衡配置
upstream backend {server backend1.example.com;server backend2.example.com;
}server {listen 80;server_name example.com;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.4 健康檢查
????????Nginx 還可以對后端服務器進行健康檢查,確保請求不會分發到不可用的服務器。通過配置?ngx_http_upstream_module
?模塊,可以實現簡單的健康檢查功能。
upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.com down;
}server {listen 80;server_name example.com;location / {proxy_pass http://backend;}
}
????????在此配置中,backend3.example.com
?被標記為?down
,Nginx 將不會將請求分發到這臺服務器。更高級的健康檢查可以通過第三方模塊如?ngx_http_upstream_check_module
?實現。
2.5 高級反向代理配置
2.5.1 緩存配置
????????Nginx 可以作為緩存服務器,通過緩存后端服務器的響應,減少后端服務器的負擔,提升響應速度。
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {listen 80;server_name example.com;location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.5.2 SSL 終止
????????Nginx 可以處理 SSL/TLS 加密,解密客戶端請求后將其轉發給后端服務器,減輕后端服務器的加密負擔。
server {listen 443 ssl;server_name example.com;ssl_certificate /etc/nginx/ssl/nginx.crt;ssl_certificate_key /etc/nginx/ssl/nginx.key;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.6 HTTPS配置
#user nobody;
worker_processes 1;#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;#log_format main '$remote_addr - $remote_user [$time_local] "$request" '# '$status $body_bytes_sent "$http_referer" '# '"$http_user_agent" "$http_x_forwarded_for"';#access_log logs/access.log main;sendfile on;#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65;#gzip on;server {listen 443 ssl;server_name mt.hello.com;#ssl on;ssl_certificate ../ssl/nj.crt;ssl_certificate_key ../ssl/nj.key;ssl_session_cache shared:SSL:1m;ssl_session_timeout 5m;ssl_ciphers HIGH:!aNULL:!MD5;ssl_prefer_server_ciphers on;location /chat/ {proxy_pass http://jd.hello.com:8089;}}server {listen 80;#填寫綁定證書的域名server_name mt.hello.com;#強制將http的URL重寫成httpsrewrite ^(.*) https://$server_name$1 permanent; }server {listen 8081;server_name mt.hello.com;location /chat/ {proxy_pass http://jd.hello.com:8089;}location /proxy/nginx/ {if ($host = 'mt.hello.com') {rewrite ^(.*)$ http://jd.hello.com/$1 permanent;}proxy_pass http://jd.hello.com:8089/;}location /proxy/ {if ($host = 'mt.hello.com') {rewrite ^(.*)$ http://www.baidu.com permanent;}proxy_pass http://jd.hello.com:8089/;}location /error/ {if ($host = 'jd.hello.com') {return 404;}proxy_pass http://jd.hello.com:8089/;}error_page 404 /404.html;error_page 500 502 503 504 /50x.html;location =/50x.html{root html;}location =/404.html{root html;}location /mystatic {root html;index index.html index.htm;}}}
3. Nginx性能優化
????????Nginx 以其高性能和高并發處理能力著稱,但在實際應用中,合理的性能優化策略仍能顯著提升其性能。本文將詳細探討 Nginx 的性能優化方法,包括配置優化、系統優化、緩存機制和高并發優化。
3.1 配置優化
????????Nginx 的配置對其性能有著至關重要的影響。合理的配置可以減少資源消耗,提高處理效率。
3.1.1 Worker 進程配置
????????Nginx 的?worker_processes
?參數決定了處理請求的工作進程數量。一般建議將其設置為等于服務器的 CPU 核心數,以充分利用多核 CPU 的并行處理能力。
????????worker_cpu_affinity:將Nginx?作進程綁定到指定的CPU核?,默認Nginx是不進?進程綁定的。
# worker_processes auto; #auto?表示自動檢測 CPU 核心數,并設置相應數量的工作進程。# 找到以下兩行,修改為合適的值
StartServers 8 # 初始啟動的進程數
MaxRequestWorkers 150 # 最大的并發請求處理數user nginx nginx; # 啟動Nginx?作進程的??和組
worker_processes [number | auto]; # 啟動Nginx?作進程的數量
worker_cpu_affinity 00000001 00000010 00000100 00001000;
# 將Nginx?作進程綁定到指定的CPU核?,默認Nginx是不進?進程綁定的,
# 綁定并不是意味著當前nginx進程獨 占以?核?CPU,但是可以保證此進程不會運?在其他核?上,
# 這就極?減少了nginx的?作進程在不同的cpu核 ?上的來回跳轉,減少了CPU對進程的資源分配與回收以及內存管理等,
#因此可以有效的提升nginx服務器的性 能。 此處CPU有四顆核心。也可寫成:
#worker_cpu_affinity 0001 0010 0100 1000;#cpu的親和能偶使nginx對于不同的work工作進程綁定到不同的cpu上面去。就能夠減少在work間不#斷切換cpu,把進程通常不會在處理器之間頻繁遷移,進程遷移的頻率小,來減少性能損耗。
#每個 worker 的線程可以把一個 cpu 的性能發揮到極致。所以 worker 數和服務器的 cpu 數相#等是最為適宜的。設少了會浪費 cpu,設多了會造成 cpu 頻繁切換上下文帶來的損耗
3.1.2 Worker 連接數配置
??worker_connections
?參數決定了每個工作進程可以處理的最大連接數。為了提高并發處理能力,建議將其設置為盡可能大的值。
events {worker_connections 1024;
}
????????這個配置表示每個工作進程最多可以處理 1024 個并發連接。
3.1.3 緩存配置
????????Nginx 提供多種緩存機制,可以緩存后端服務器的響應,減少后端服務器的壓力,提高響應速度。常用的緩存機制包括 FastCGI 緩存和代理緩存。
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {listen 80;server_name example.com;location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
????????這個配置創建了一個緩存區域?my_cache
,并在反向代理時啟用了緩存。
3.2 系統優化
????????除了 Nginx 的配置優化,對操作系統的優化也能顯著提高 Nginx 的性能。
3.2.1 文件描述符限制
????????Nginx 處理大量并發連接時,需要打開大量的文件描述符。默認的文件描述符限制可能不足,需通過修改系統配置提高限制。
# 臨時修改
ulimit -n 65535# 永久修改,編輯 /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
3.2.2 TCP 連接優化
????????調整 TCP 連接參數,可以減少網絡延遲,提高并發處理能力。
# 調整內核參數,編輯 /etc/sysctl.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30# 應用配置
sysctl -p
3.3 緩存機制
????????緩存是提升 Nginx 性能的重要手段。通過緩存機制,Nginx 可以將后端服務器的響應存儲在本地,減少后端服務器的負載。
3.3.1 FastCGI 緩存
????????FastCGI 緩存用于緩存 FastCGI 應用程序的響應,例如 PHP。
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=fastcgi_cache:10m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";server {location ~ \.php$ {fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;fastcgi_index index.php;include fastcgi_params;fastcgi_cache fastcgi_cache;fastcgi_cache_valid 200 60m;fastcgi_cache_use_stale error timeout invalid_header updating;}
}
3.3.2 代理緩存
????????代理緩存用于緩存反向代理的響應,減少后端服務器的負載。
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
3.4 高并發優化
????????Nginx 在處理高并發連接時,通過異步非阻塞的事件驅動模型,能夠高效地處理大量并發連接。以下是一些針對高并發場景的優化策略。
3.4.1 啟用 keepalive
? ?keepalive
?可以保持客戶端和服務器之間的連接,提高連接重用率,減少連接建立和釋放的開銷。
upstream backend {server backend1.example.com;server backend2.example.com;keepalive 32;
}server {location / {proxy_pass http://backend;proxy_http_version 1.1;proxy_set_header Connection "";}
}
3.4.2 調整緩沖區大小
????????調整 Nginx 的緩沖區大小,可以提高大文件傳輸的效率,減少內存碎片。
http {server {client_body_buffer_size 16K;client_header_buffer_size 1k;large_client_header_buffers 4 16k;output_buffers 1 32k;postpone_output 1460;}
}
3.4.3 啟用 Gzip 壓縮
????????啟用 Gzip 壓縮,可以減少傳輸的數據量,提高響應速度。
http {gzip on;gzip_types text/plain application/xml;gzip_min_length 1000;gzip_comp_level 5;
}