2011-01-21 46 views
16

我想了解是什麼讓Nginx如此之快,並且我有幾個問題。nginx:它的多線程,但使用多個進程?

據我瞭解,無論是阿帕奇產生一個新的進程來服務於每個請求或產生一個新的線程來滿足每個請求。由於每個新線程共享虛擬地址空間,因此如果有多個併發請求進來,則內存使用量會持續增長。

Nginx通過只有一個監聽進程(主服務器)和單個執行線程AND 2或3 (編號是可配置的)工作進程。這個主進程/線程正在運行一個事件循環。有效等待任何傳入的請求。當請求進入時,它將請求發送給其中一個工作進程。

請糾正我,如果我的上述認識是不正確

如果上面的是正確的,那麼我有幾個問題:

1)是不是工作進程會產生多個線程,會遇到與Apache相同的問題?

2)或者是nginx的快,因爲它的基礎架構的情況下使用非阻塞-IO骨子裏。也許工作進程產生線程,只有非阻塞IO,是嗎?

3)什麼「究竟」是「基於事件的架構」,可真有人把它簡化,對於像我soemone理解。它是否僅適用於非阻塞io或其他內容?

我的c10k參考,我想通過它,但我不認爲其對基於事件的牌坊。它似乎更多的非阻塞IO。

+0

非阻塞IO需要基於事件的體系結構。 – 2011-01-21 23:08:34

+0

僅供參考 - 以防萬一你有興趣深入挖掘 - 我已經在此回答了其他材料+視頻的答案:http://planetunknown.blogspot.com/2011/02/why-nginx-is-faster- than-apache.html – PlanetUnknown 2013-10-02 14:18:06

回答

17

從概念的角度來看,這並不複雜。我會盡量清楚,但我必須做一些簡化。

基於事件的服務器(如nginxlighttpd)使用事件監視系統的包裝。例如。 lighttpd使用libevent來抽象更高級的高速事件監控系統(同樣參見libev)。

服務器跟蹤所有它具有使用簡單的狀態機的每個連接(包括寫和讀)的無阻塞連接。事件監控系統會在有新數據可用或何時可以寫入更多數據時通知服務器進程。它就像一個select()類固醇,如果你知道套接字編程。服務器進程然後簡單地發送使用一些先進功能所需的文件等sendfile()在可能或變爲使用用於通信的套接字的請求到一個CGI處理(此插座將與該事件監控系統等的其他網絡連接進行監控。)

This作爲關於nginx內部的大量信息的鏈接,以防萬一。我希望它有幫助。

+0

感謝Ass3mbler。我認爲這有助於理解它。 – PlanetUnknown 2011-01-22 13:57:37

46

Apache使用多個線程爲每個請求提供它自己的執行線程。在使用同步I/O時,這是避免阻塞的必要條件。

Nginx只使用異步I/O,這使得阻塞成爲一個非問題。 nginx使用多進程的唯一原因是要充分利用多核,多CPU和超線程系統。即使有了SMP支持,內核也無法在多個CPU上安排單個執行線程。每個邏輯CPU至少需要一個進程或線程。

所以不同的是,nginx的要求足夠的工作進程,以獲得SMP的全部好處,而Apache的架構必要創建每個請求一個新的線程(每個都有它自己的身邊〜8MB的堆)。顯然,在併發性較高的情況下,Apache將使用更多的內存,並因維護大量線程而承受更大的開銷。

6

Apache不會爲每個請求產生一個新線程。它維護一個線程緩存或一組預處理的進程,它將請求發送給它。併發請求的數量受到子/線程數量的限制,但是apache並不會爲每個請求產生一個新的線程/子進程,而這個請求的速度會非常慢(即使使用線程,創建和拆卸每個請求的速度都會太慢)

Nginx使用了一個master-worker模型。主進程處理加載配置和創建/銷燬/維護工作人員。像Apache一樣,它開始時已經有一些預分叉的進程在運行,每個進程都是一個工作者(其中之一是「主」進程)。每個工作進程共享一組偵聽套接字。每個工作進程接受連接並處理它們,但每個工作人員可以一次處理幾千個連接,而不像apache,每個工作只能處理1個連接。

nginx實現這一點的方式是通過「多路複用」。它不使用libevent,它使用專門爲nginx設計的自定義事件循環,並隨着nginx軟件的發展而在開發中不斷髮展。多路複用的工作原理是使用一個循環,通過一個數據/新連接/每個連接/對象每循環迭代操作的塊對程序塊進行「增量」操作。它全部基於像Epoll()kqueue()和select()這樣的後端。您應該閱讀的內容