【效能調優專題】【Nginx調優】【Nginx快速掌握】【Nginx原理】
基本原理
Nginx 的程序模型
Nginx 伺服器,正常執行過程中:
多程序
:一個 Master 程序、多個 Worker 程序
Master 程序
:管理 Worker 程序
對外介面:接收
外部的操作
(訊號)
對內轉發:根據
外部的操作
的不同,透過
訊號
管理 Worker
監控:監控 worker 程序的執行狀態,worker 程序異常終止後,自動重啟 worker 程序
Worker 程序
:所有 Worker 程序都是平等的
實際處理:網路請求,由 Worker 程序處理;
Worker 程序數量:在 nginx。conf 中配置,一般設定為
核心數
,充分利用 CPU 資源,同時,避免程序數量過多,避免程序競爭 CPU 資源,增加上下文切換的損耗。
思考:
請求是連線到 Nginx,Master 程序負責處理和轉發?
如何選定哪個 Worker 程序處理請求?請求的處理結果,是否還要經過 Master 程序?
HTTP 連線建立和請求處理過程:
Nginx 啟動時,Master 程序,載入配置檔案
Master 程序,初始化監聽的 socket
Master 程序,fork 出多個 Worker 程序
Worker 程序,競爭新的連線,獲勝方透過三次握手,建立 Socket 連線,並處理請求
Nginx 高效能、高併發:
Nginx 採用:
多程序
+
非同步非阻塞
方式(
IO 多路複用
epoll)
請求的完整過程:
建立連線
讀取請求:解析請求
處理請求
響應請求
請求的完整過程,對應到底層,就是:讀寫 socket 事件
Nginx 的事件處理模型
request:Nginx 中 http 請求。
基本的 HTTP Web Server 工作模式:
接收請求
:逐行讀取
請求行
和
請求頭
,判斷段有請求體後,讀取
請求體
處理請求
返回響應
:根據處理結果,生成相應的 HTTP 請求(
響應行
、
響應頭
、
響應體
)
Nginx 也是這個套路,整體流程一致。
模組化體系結構
nginx的模組根據其功能基本上可以分為以下幾種型別:
event module
: 搭建了獨立於作業系統的事件處理機制的框架,及提供了各具體事件的處理。包括ngx_events_module, ngx_event_core_module和ngx_epoll_module等。nginx具體使用何種事件處理模組,這依賴於具體的作業系統和編譯選項。
phase handler
: 此型別的模組也被直接稱為handler模組。主要負責處理客戶端請求併產生待響應內容,比如ngx_http_static_module模組,負責客戶端的靜態頁面請求處理並將對應的磁碟檔案準備為響應內容輸出。
output filter
: 也稱為filter模組,主要是負責對輸出的內容進行處理,可以對輸出進行修改。例如,可以實現對輸出的所有html頁面增加預定義的footbar一類的工作,或者對輸出的圖片的URL進行替換之類的工作。
upstream
: upstream模組實現反向代理的功能,將真正的請求轉發到後端伺服器上,並從後端伺服器上讀取響應,發回客戶端。upstream模組是一種特殊的handler,只不過響應內容不是真正由自己產生的,而是從後端伺服器上讀取的。
load-balancer
: 負載均衡模組,實現特定的演算法,在眾多的後端伺服器中,選擇一個伺服器出來作為某個請求的轉發伺服器。
常見問題剖析
Nginx vs. Apache
nginx vs。 apache:
http://www。
oschina。net/translate/n
ginx-vs-apache
網路 IO 模型:
nginx:IO 多路複用,epoll(freebsd 上是 kqueue )
高效能
高併發
佔用系統資源少
apache:阻塞 + 多程序/多執行緒
更穩定,bug 少
模組更豐富
場景:
處理多個請求時,可以採用:
IO 多路複用
或者
阻塞 IO
+
多執行緒
IO 多路服用
:
一個
執行緒
,跟蹤多個 socket 狀態,哪個
就緒
,就讀寫哪個;
阻塞 IO
+
多執行緒
:每一個請求,新建一個服務執行緒
思考
:
IO 多路複用
和
多執行緒
的適用場景?
IO 多路複用
:單個連線的請求處理速度沒有優勢,適合
IO 密集型
場景,事件驅動
大併發量
:只使用一個執行緒,處理大量的併發請求,降低
上下文環境
切換損耗,也不需要考慮併發問題,相對可以處理更多的請求;
消耗更少的系統資源(不需要
執行緒排程開銷
)
適用於
長連線
的情況(多執行緒模式
長連線
容易造成
執行緒過多
,造成
頻繁排程
)
阻塞IO
+
多執行緒
:實現簡單,可以不依賴系統呼叫,適合
CPU 密集型
場景
每個執行緒,都需要時間和空間;
執行緒數量增長時,執行緒排程開銷指數增長
Nginx 最大連線數
基礎背景:
Nginx 是多程序模型,Worker 程序用於處理請求;
單個程序的連線數(檔案描述符 fd),有上限(
nofile
):
ulimit -n
Nginx 上配置單個 worker 程序的最大連線數:
worker_connections
上限為
nofile
Nginx 上配置 worker 程序的數量:
worker_processes
因此,Nginx 的最大連線數:
Nginx 的最大連線數:
Worker 程序數量
x
單個 Worker 程序的最大連線數
上面是 Nginx 作為通用伺服器時,最大的連線數
Nginx 作為
反向代理
伺服器時,能夠服務的最大連線數:(
Worker 程序數量
x
單個 Worker 程序的最大連線數
)/ 2。
Nginx 反向代理時,會建立
Client 的連線
和
後端 Web Server 的連線
,佔用 2 個連線
思考:
每開啟一個 socket 佔用一個 fd
為什麼,
一個程序
能夠開啟的 fd 數量有限制?
附錄
HTTP 請求和響應
HTTP 請求:
請求行:
method
、
uri
、
http version
請求頭
請求體
HTTP 響應:
響應行:
http version
、
status code
響應頭
響應體
IO 模型
場景:
處理多個請求時,可以採用:
IO 多路複用
或者
阻塞 IO
+
多執行緒
IO 多路服用
:
一個
執行緒
,跟蹤多個 socket 狀態,哪個
就緒
,就讀寫哪個;
阻塞 IO
+
多執行緒
:每一個請求,新建一個服務執行緒
思考:
IO 多路複用
和
多執行緒
的適用場景?
IO 多路複用
:單個連線的請求處理速度沒有優勢
大併發量
:只使用一個執行緒,處理大量的併發請求,降低
上下文環境
切換損耗,也不需要考慮併發問題,相對可以處理更多的請求;
消耗更少的系統資源(不需要
執行緒排程開銷
)
適用於
長連線
的情況(多執行緒模式
長連線
容易造成
執行緒過多
,造成
頻繁排程
)
阻塞IO
+
多執行緒
:實現簡單,可以不依賴系統呼叫。
每個執行緒,都需要時間和空間;
執行緒數量增長時,執行緒排程開銷指數增長
select/poll 和 epoll 比較
詳細內容,參考:
select poll epoll三者之間的比較
select/poll 系統呼叫:
// select 系統呼叫
int
select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
// poll 系統呼叫
int poll(struct pollfd fds[],
nfds_t nfds,
int timeout);
select
:
查詢 fd_set 中,是否有
就緒
的
fd
,可以設定一個
超時時間
,當有 fd (File descripter) 就緒或超時返回;
fd_set 是一個
位集合
,大小是在
編譯核心
時的常量,預設大小為 1024
特點:
連線數限制
,fd_set 可表示的 fd 數量太小了;
線性掃描
:判斷 fd 是否就緒,需要遍歷一邊 fd_set;
資料複製
:使用者空間和核心空間,複製
連線就緒狀態
資訊
poll
:
解決了
連線數限制
:
poll 中將 select 中的 fd_set 替換成了一個 pollfd
陣列
解決
fd 數量過小
的問題
資料複製
:使用者空間和核心空間,複製
連線就緒狀態
資訊
epoll
: event 事件驅動
事件機制
:避免
線性掃描
為每個 fd,
註冊
一個
監聽事件
fd 變更為
就緒
時,將 fd 新增到
就緒連結串列
fd 數量
:無限制(OS 級別的限制,單個程序能開啟多少個 fd)
select,poll,epoll:
I/O多路複用
的機制;
I/O多路複用
就透過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。
監視
多個檔案描述符
但select,poll,epoll本質上都是
同步I/O
:
使用者程序
負責
讀寫
(從
核心空間
複製到
使用者空間
),讀寫過程中,使用者程序是阻塞的;
非同步 IO
,無需使用者程序負責讀寫,非同步IO,會負責從
核心空間
複製到
使用者空間
;
Nginx 的併發處理能力
關於 Nginx 的併發處理能力:
併發連線數,一般最佳化後,峰值能保持在 1~3w 左右。(記憶體和 CPU 核心數不同,會有進一步最佳化空間)