Nginx架構賞析

2022-07-07 08:45:14 字數 2506 閱讀 3951

**的某位大佬曾經做過測試,在一台24g記憶體的機器上,nginx的最大併發連線數達到了200萬。同學們聽到這個結論後,是不是被nginx的超高效能深深折服了,它內部的架構設計究竟是怎麼樣的呢?這篇文章就帶同學們來認識一下nginx的架構設計吧。

nginx程序模型

nginx預設以多程序的方式啟動執行,當然nginx也是支援多執行緒的方式的,只是我們主流的方式還是多程序的方式,也是nginx的預設方式。nginx採用多程序的方式有很多的好處,這一點與我們大部分同學們的認知發生衝突了。大部分同學會說程序比執行緒重,程序更耗費資源等等,總之可以說出一大堆執行緒優於程序的證明。如果有同學恰恰是這樣想的,那就得擴充下認知啦。比如我們大名鼎鼎的redis,oracle裡邊都是有多程序概念的 ,而這些軟體無一例外都具有超高效能。所以,我們今天就主要來學習下nginx的多程序模式。

nginx的程序模型長個什麼樣子,廢話不多說,直接上圖。

nginx在啟動後,會有乙個master程序和多個worker程序。master程序主要用來管理worker程序,包含:接收來自作業系統的訊號,向各worker程序傳送訊號,監控worker程序的執行狀態,當worker程序退出後(異常情況下),會自動重新啟動新的worker程序。而基本的網路事件,則是放在worker程序中來處理了。多個worker程序之間是對等的,他們同等競爭來自客戶端的請求,各程序互相之間是獨立的。乙個請求,只可能在乙個worker程序中處理,乙個worker程序,不可能處理其它worker程序的請求。worker程序的個數是可以設定的,一般設定與機器cpu核數一致,這裡面的原因與nginx的程序模型以及事件處理模型是分不開的。

我們知道了在操作nginx的時候,nginx內部做了些什麼事情,那麼,worker程序又是如何客戶端處理請求的呢?我們前面有提到,worker程序之間是平等的,每個程序,處理請求的機會也是一樣的。當我們提供80埠的http服務時,乙個連線請求過來,每個程序都有可能處理這個連線,怎麼做到的呢?首先,每個worker程序都是從master程序fork過來,在master程序裡面,先建立好serversocket,開啟監聽,然後再fork出多個worker程序。所有worker程序都將和master程序持有同乙份socket控制代碼,並且控制代碼會在新連線到來時變得可讀,為保證只有乙個程序處理該連線,所有worker程序在註冊控制代碼讀事件前搶accept_mutex,搶到互斥鎖的那個程序註冊控制代碼讀事件,在讀事件裡呼叫accept接受該連線。當乙個worker程序在accept這個連線之後,就生成了乙個新的socket,通過這個socket開始讀取請求,解析請求,處理請求,產生資料後,再返回給客戶端,最後才斷開連線,乙個完整的請求就是這樣玩完了。我們可以看到,乙個請求,完全由worker程序來處理,而且只在乙個worker程序中處理。

那麼,nginx採用這種程序模型有什麼好處呢?實在是太多了,重點說上幾條。首先,對於每個worker程序來說,獨立的程序,不需要加鎖,所以省掉了鎖帶來的開銷,同時在程式設計以及問題查詢時,也會方便很多。其次,採用獨立的程序,可以讓互相之間不會影響,乙個程序退出後,其它程序還在工作,服務不會中斷,master程序則很快啟動新的worker程序。當然,worker程序的異常退出,肯定是程式有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。當然,好處還有很多,同學們可以慢慢體會。

nginx事件模型

nginx採用了nio的方式來處理請求,這是nginx可以同時處理成千上萬個請求的根本原因。想想低版本tomcat的io模型(高版本已支援nio),每個請求會獨佔乙個工作執行緒,當併發數上到幾千時,就同時有幾千的執行緒在處理請求了。這對作業系統來說,是個不小的挑戰,執行緒帶來的記憶體占用非常大,執行緒的上下文切換帶來的cpu開銷很大,自然效能就上不去了,而這些開銷完全是沒有意義的。

nginx為什麼要使用nio呢?nio到底是怎麼回事呢?io的本質就是讀寫事件,而當讀寫事件沒有準備好時,必然不可操作,如果不用非阻塞的方式來呼叫,那就得阻塞呼叫了,事件沒有準備好,那就只能等了,等事件準備好了,工作執行緒再繼續吧。阻塞呼叫會進入核心等待,cpu就會讓出去給別人用了,工作執行緒只能傻傻的睡覺等待,對單執行緒的worker來說,顯然不合適,當網路事件越多時,大家都在等待呢,cpu空閒下來沒人用,cpu利用率自然上不去了,更別談高併發了。所以,為了高效能,必須使用nio。關於nio,我們這裡就是一筆帶過,想詳細學習的同學可以去看我的nio原始碼分析文章。

接下來,我們使用一段偽**來總結一下nginx的事件處理模型吧。

date now;	// 表示當前時間

while (true) else

// 通過epoll拿到已經就緒的事件

nevents = epoll(events, timeout);

// 挨個遍歷處理事件

for i in nevents:

task task;

// 讀事件

if (events[i].type == read) else

// 防到乙個專門的執行佇列裡

tasks(task);

}

nginx基礎架構

網路效能 單次請求的延遲性 網路效率 可進化性 可擴充套件性 可定製性 可配置性 可重用性 關鍵元件的運 況可以被監控的程度 所有模組都遵循同樣的ngx module t介面設計規範,這種方式帶來了良好的簡單性 靜態可擴充套件性 可重用性 模組的基本介面ngx module t足夠簡單,只涉及模組的...

nginx常見架構

服務 nginx負載均衡 nginx快取服務 快取 1 靜態資源web服務 檔案讀取sendfile tcp nopush tcp nodelay 壓縮,預讀gzip模組 2 服務 3 負載均衡排程器slb 4 動態快取 新增cache control expires頭 靜態資源訪問 壓縮 list...

柳永《蝶戀花》賞析

柳永 蝶戀花 佇倚危樓風細細,望極春愁,黯黯生天際。草色煙光殘照裡,無言誰會憑闌意?擬把疏狂圖一醉,對酒當歌,強樂還無味。衣帶漸寬終不悔,為伊消得人憔悴。賞析 這是一首懷人之作。詞人把漂泊異鄉的落魄感受,同懷念意中人的纏綿情思結合在一起寫,採用 曲徑通幽 的表現方式,抒情寫景,感情真摯。上片寫登 樓...