首頁 運維 Nginx nginx效能為什麼好

nginx效能為什麼好

Jun 12, 2019 am 10:11 AM
nginx效能

nginx效能為什麼好

nginx在啟動後,在unix系統中會以daemon的方式在背景執行,後台程式包含一個master行程和多個worker行程。我們也可以手動地關掉後台模式,讓nginx在前台運行,並且透過配置讓nginx取消master進程,從而可以使nginx以單一進程方式運行。

很顯然,生產環境下我們肯定不會這麼做,所以關閉後台模式,一般是用來調試用的,在後面的章節裡面,我們會詳細地講解如何調試nginx。

所以,我們可以看到,nginx是以多進程的方式來工作的,當然nginx也是支援多執行緒的方式的,只是我們主流的方式還是多進程的方式,也是nginx的預設方式。 nginx採用多進程的方式有諸多好處,所以我就主要講解nginx的多進程模式吧。

剛剛講到,nginx在啟動後,會有一個master進程和多個worker進程。 master進程主要用來管理worker進程,包含:接收來自外界的訊號,向各worker進程發送訊號,監控worker進程的運作狀態,當worker進程退出後(異常情況下),會自動重新啟動新的worker進程。

而基本的網路事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程相互之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。 worker進程的數量是可以設定的,一般我們會設定與機器cpu核數一致,這裡面的原因與nginx的進程模型以及事件處理模型是分不開的。

在nginx啟動後,如果我們要操作nginx,要怎麼做呢?

從上文我們可以看到,master來管理worker進程,所以我們只需要與master進程通訊就行了。 master進程會接收來自外界發來的訊號,再根據訊號做不同的事情。所以我們要控制nginx,只需要透過kill向master進程發送訊號就行了。例如kill -HUP pid,則是告訴nginx,從容地重啟nginx,我們一般用這個訊號來重啟nginx,或重新載入配置,因為是從容地重啟,因此服務是不中斷的。 master行程在接收HUP訊號後是怎麼做的呢?

首先master進程在接到訊號後,會先重新載入設定文件,然後再啟動新的worker進程,並向所有舊的worker進程發送訊號,告訴他們可以光榮退休了。

新的worker在啟動後,就開始接收新的請求,而舊的worker在收到來自master的訊號後,就不再接收新的請求,並且在目前進程中的所有未處理完的請求處理完成後,再退出。

當然,直接給master進程發送訊號,這是比較老的操作方式,nginx在0.8版本之後,引入了一系列命令列參數,來方便我們管理。例如,./nginx -s reload,就是來重啟nginx,./nginx -s stop,就是來停止nginx的運作。

如何做到的呢?

我們還是拿reload來說,我們看到,執行指令時,我們是啟動一個新的nginx進程,而新的nginx進程在解析到reload參數後,就知道我們的目的是控制nginx來重新載入設定檔了,它會向master進程發送訊號,然後接下來的動作,就跟我們直接向master進程發送訊號一樣了。

現在,我們知道了當我們在操作nginx的時候,nginx內部做了些什麼事情,那麼,worker進程又是如何處理請求的呢?我們前面有提到,worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80埠的http服務時,一個連接請求過來,每個行程都有可能處理這個連接,怎麼做到的呢?

首先,每個worker行程都是從master行程fork過來,在master行程裡面,先建立好需要listen的socket(listenfd)之後,再fork出多個worker行程。所有worker進程的listenfd會在新連接到來時變得可讀,為確保只有一個進程處理該連接,所有worker進程在註冊listenfd讀取事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀取事件,在讀取事件裡呼叫accept接受該連線。

當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。

多執行緒模型 VS 多進程模型,這是個問題!

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

上面講了很多關於nginx的進程模型,接下來,我們來看看nginx是如何處理事件的。

有人可能要問了,nginx採用多worker的方式來處理請求,每個worker裡面只有一個主線程,那能夠處理的並發數很有限啊,多少個worker就能處理多少個並發,何來高並發呢?非也,這就是nginx的高明之處,nginx採用了非同步非阻塞的方式來處理請求,也就是說,nginx是可​​以同時處理成千上萬個請求的。

想想apache的常用工作方式(apache也有異步非阻塞版本,但因其與自帶某些模組衝突,所以不常用),每個請求會獨佔一個工作線程,當並發數上到幾千時,就同時有幾千的線程在處理請求了。這對作業系統來說,是個不小的挑戰,執行緒帶來的記憶體佔用非常大,執行緒的上下文切換帶來的cpu開銷很大,自然效能就上不去了,而這些開銷完全是沒有意義的。

同步阻塞 VS 非同步非阻塞

為什麼nginx可以採用非同步非阻塞的方式來處理呢,或是非同步非阻塞到底是怎麼回事呢?我們先回到原點,看看一個請求的完整過程。首先,請求過來,要建立連接,然後再接收數據,接收數據後,再發送數據。具體到系統底層,就是讀寫事件,而當讀寫事件沒有準備好時,必然不可操作,如果不用非阻塞的方式來調用,那就得阻塞調用了,事件沒有準備好,那就只能等了,等事件準備好了,你再繼續吧。阻塞呼叫會進入核心等待,cpu就會讓出去給別人用了,對單線程的worker來說,顯然不合適,當網路事件越多時,大家都在等待呢,cpu空閒下來沒人用,cpu利用率自然上不去了,更別談高並發了。

好吧,你說加進程數,這跟apache的執行緒模型有什麼差別,注意,別增加無謂的上下文切換。所以,在nginx裡面,最忌諱阻塞的系統呼叫了。不要阻塞,那就非阻塞嘍。非阻塞就是,事件還沒準備好,馬上回到EAGAIN,告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。好吧,你過一會,再來檢查一下事件,直到事件準備好了為止,在這期間,你就可以先去做其它事情,然後再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你可以做更多的事情了,但帶來的開銷也是不小的。所以,才會有了非同步非阻塞的事件處理機制,具體到系統呼叫就是像select/poll/epoll/kqueue這樣的系統呼叫。

它們提供了一種機制,讓你可以同時監控多個事件,調用他們是阻塞的,但可以設定超時時間,在超時時間之內,如果有事件準備好了,就返回。這個機制正好解決了我們上面的兩個問題,拿epoll為例(在後面的例子中,我們多以epoll為例子,以代表這一類函數),當事件沒準備好時,放到epoll裡面,事件準備好了,我們就去讀寫,當讀寫返回EAGAIN時,我們將它再次加入到epoll裡面。這樣,只要有事件準備好了,我們就去處理它,只有當所有事件都沒準備好時,才在epoll裡面等著。這樣,我們就可以並發處理大量的並發了,當然,這裡的並發請求,是指未處理完的請求,線程只有一個,所以同時能處理的請求當然只有一個了,只是在請求間進行不斷地切換而已,切換也是因為非同步事件未準備好,而主動讓出的。這裡的切換是沒有任何代價,你可以理解為循環處理多個準備好的事件,事實上就是這樣的。

與多線程相比,這種事件處理方式是有很大的優勢的,不需要創建線程,每個請求佔用的內存也很少,沒有上下文切換,事件處理非常的輕量級級。並發數再多也不會導致無謂的資源浪費(上下文切換)。更多的並發數,只是會佔用更多的記憶體而已。我之前有對連線數進行過測試,在24G記憶體的機器上,處理的並發請求數達到200萬。現在的網頁伺服器基本上都採用這種方式,這也是nginx效能高效的主要原因。

我們之前說過,推薦設定worker的個數為cpu的核數,在這裡就很容易理解了,更多的worker數,只會導致進程來競爭cpu資源了,從而帶來不必要的上下文切換。

而且,nginx為了更好的利用多核心特性,提供了cpu親緣性的綁定選項,我們可以將某一個進程綁定在某一個核上,這樣就不會因為進程的切換帶來cache的失效。像這種小的優化在nginx中非常常見,同時也說明了nginx作者的苦心孤詣。例如,nginx在做4個位元組的字串比較時,會將4個字元轉換成一個int型,再作比較,以減少cpu的指令數等等。

現在,知道了nginx為什麼會選擇這樣的行程模型與事件模型了。對於一個基本的web伺服器來說,事件通常有三種類型,網路事件、訊號、定時器。從上面的講解中知道,網路事件透過非同步非阻塞可以很好的解決掉。如何處理訊號與定時器?

首先,訊號的處理。

對nginx來說,有一些特定的訊號,代表著特定的意義。訊號會中斷掉程式目前的運行,改變狀態後,繼續執行。如果是系統調用,則可能會導致系統調用的失敗,需要重入。關於訊號的處理,大家可以學習一些專業書籍,這裡不多說。對於nginx來說,如果nginx正在等待事件(epoll_wait時),如果程式收到訊號,在訊號處理函數處理完後,epoll_wait會回傳錯誤,然後程式可再次進入epoll_wait呼叫。

另外,再來看看定時器。由於epoll_wait等函數在呼叫的時候是可以設定一個超時時間的,所以nginx借助這個超時時間來實現定時器。 nginx裡面的定時器事件是放在一顆維護定時器的紅黑樹裡面,每次在進入epoll_wait前,先從該紅黑樹裡面拿到所有定時器事件的最小時間,在計算出epoll_wait的超時時間後進入epoll_wait。

所以,當沒有事件產生,也沒有中斷訊號時,epoll_wait會超時,也就是說,計時器事件到了。這時,nginx會檢查所有的逾時事件,將他們的狀態設為超時,然後再去處理網路事件。由此可以看出,當我們寫nginx程式碼時,在處理網路事件的回呼函數時,通常做的第一個事情就是判斷超時,然後再去處理網路事件。

更多Nginx相關知識,訪問Nginx使用教學欄位! 

以上是nginx效能為什麼好的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1677
14
CakePHP 教程
1431
52
Laravel 教程
1333
25
PHP教程
1279
29
C# 教程
1257
24
NGINX單元:關鍵功能 NGINX單元:關鍵功能 Apr 25, 2025 am 12:17 AM

NGINXUnit是一個開源應用服務器,支持多種編程語言,提供動態配置、零停機更新和內置負載均衡等功能。 1.動態配置:無需重啟即可修改配置。 2.多語言支持:兼容Python、Go、Java、PHP等。 3.零停機更新:支持不中斷服務的應用更新。 4.內置負載均衡:可將請求分發到多個應用實例。

nginx和apache:了解關鍵差異 nginx和apache:了解關鍵差異 Apr 26, 2025 am 12:01 AM

NGINX和Apache各有優劣,選擇應基於具體需求。 1.NGINX適合高並發場景,因其異步非阻塞架構。 2.Apache適用於需要復雜配置的低並發場景,因其模塊化設計。

NGINX單元:支持不同的編程語言 NGINX單元:支持不同的編程語言 Apr 16, 2025 am 12:15 AM

NGINXUnit支持多種編程語言,通過模塊化設計實現。 1.加載語言模塊:根據配置文件加載相應模塊。 2.應用啟動:調用語言運行時執行應用代碼。 3.請求處理:將請求轉發給應用實例。 4.響應返回:將處理後的響應返回給客戶端。

NGINX與Apache:性能,可伸縮性和效率 NGINX與Apache:性能,可伸縮性和效率 Apr 19, 2025 am 12:05 AM

NGINX和Apache都是強大的Web服務器,各自在性能、可擴展性和效率上有獨特的優勢和不足。 1)NGINX在處理靜態內容和反向代理時表現出色,適合高並發場景。 2)Apache在處理動態內容時表現更好,適合需要豐富模塊支持的項目。選擇服務器應根據項目需求和場景來決定。

NGINX與Apache:Web服務器的比較分析 NGINX與Apache:Web服務器的比較分析 Apr 21, 2025 am 12:08 AM

NGINX更适合处理高并发连接,而Apache更适合需要复杂配置和模块扩展的场景。1.NGINX以高性能和低资源消耗著称,适合高并发。2.Apache以稳定性和丰富的模块扩展闻名,适合复杂配置需求。

NGINX單元:架構及其工作原理 NGINX單元:架構及其工作原理 Apr 23, 2025 am 12:18 AM

NGINXUnit通過其模塊化架構和動態重配置功能提高了應用的性能和可管理性。 1)模塊化設計包括主控進程、路由器和應用進程,支持高效管理和擴展。 2)動態重配置允許在運行時無縫更新配置,適用於CI/CD環境。 3)多語言支持通過動態加載語言運行時實現,提升了開發靈活性。 4)高性能通過事件驅動模型和異步I/O實現,即使在高並發下也保持高效。 5)安全性通過隔離應用進程提高,減少應用間相互影響。

NGINX與Apache:檢查優點和缺點 NGINX與Apache:檢查優點和缺點 Apr 27, 2025 am 12:05 AM

NGINX適合處理高並發和靜態內容,Apache則適用於復雜配置和動態內容。 1.NGINX高效處理並發連接,適合高流量場景,但處理動態內容需額外配置。 2.Apache提供豐富模塊和靈活配置,適合複雜需求,但高並發性能較差。

終極攤牌:nginx vs. apache 終極攤牌:nginx vs. apache Apr 18, 2025 am 12:02 AM

NGINX適合處理高並發請求,Apache適合需要復雜配置和功能擴展的場景。 1.NGINX採用事件驅動、非阻塞架構,適用於高並發環境。 2.Apache採用進程或線程模型,提供豐富的模塊生態系統,適合複雜配置需求。

See all articles