2010-04-06 96 views

回答

64

如果你正在尋找寫一個套接字服務器,一個很好的起點是從幾年Dan Kegel的C10K文章後面:

http://www.kegel.com/c10k.html

我還發現Beej指南網絡編程是相當方便:

http://beej.us/guide/bgnet/

最後,如果你需要一個很好的參考,還有由理查德·史蒂文斯等UNIX網絡編程。人:

http://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/ref=dp_ob_title_bk

總之,要回答你的問題,Apache和Nginx的之間的主要區別是,Apache使用每個客戶端一個線程與阻塞I/O,而Nginx的是單線程與非阻塞I/O。 Apache的工作池確實減少了啓動和刪除進程的開銷,但是在爲多個客戶端提供服務時,它仍然使得CPU在多個線程之間切換。另一方面,Nginx可以處理一個線程中的所有請求。當一個請求需要發出網絡請求時(比如對後端),Nginx將回調附加到後端請求,然後處理另一個活動的客戶端請求。實際上,這意味着它返回到事件循環(epollkqueueselect)並要求提供要報告的文件描述符。請注意,主事件循環中的系統調用實際上是一種阻塞操作,因爲除非文件描述符中的一個準備好讀取或寫入,否則無需執行任何操作。因此,這是Nginx和Tornado在爲多個同時客戶端提供服務時的主要​​原因:只有一個進程(從而節省RAM)和只有一個線程(從而從上下文切換節省CPU)。至於epoll,它只是一個更有效的選擇版本。如果有N個打開的文件描述符(套接字),它可以讓您選擇準備在O(1)中讀取的文件,而不是O(N)時間。事實上,如果您使用--with-select_module選項進行編譯,Nginx可以使用select而不是epoll,我敢打賭它仍然比Apache更高效。我並不熟悉Apache的內部構件,但是快速的grep顯示它使用select和epoll - 可能在服務器正在監聽多個端口/接口時,或者它對一個客戶端執行同時後端請求時。

順便說一句,我開始嘗試寫這個基本的套接字服務器,想弄清楚Nginx是如此的高效。在仔細閱讀Nginx源代碼並閱讀上面鏈接的指南/書籍後,我發現編寫Nginx模塊而不是我自己的服務器會更容易。於是誕生了現在半傳奇Emiller指南Nginx的模塊開發:

http://www.evanmiller.org/nginx-modules-guide.html

(注意:該指南是書面反對Nginx的0.5-0.6和API可能已經改變。)如果你正在做的事情與HTTP,我會說給Nginx一個鏡頭,因爲它處理了愚蠢的客戶處理所有毛茸茸的細節。例如,我爲了好玩而寫的小套接字服務器與所有客戶端一起工作得很好 - 除了Safari之外,我從未想出爲什麼。即使對於其他協議,Nginx也許是正確的選擇。這些事件很好地從協議中抽象出來,這就是爲什麼它可以代理HTTP和IMAP。 Nginx的代碼基礎非常完善,編寫得很好,但有一個例外是值得一提的。當涉及到手動協議解析器時,我不會效仿它;相反,使用解析器生成器。我已經寫了一些東西,關於使用解析器生成(Ragel)與Nginx的位置:

http://www.evanmiller.org/nginx-modules-guide-advanced.html#parsing

這一切比你想可能更多的信息,但希望你會發現一些有用。

+0

這正是我需要的,非常感謝! – 2010-05-25 01:39:05

+0

Omg,謝謝你! – Caio 2010-08-24 21:05:31

5

是和否。雖然他們都使用epoll,但在技術上他們都使用事件循環來處理請求。您可以在wikipedia找到更多關於什麼事件循環以及如何使用它們的信息。

檢出libevent(由gevent使用,通常比龍捲風更加穩定的更快速&)或libev的實現。

+0

請問您能更具體一些,我可以在哪裏找到關於所有這些東西的更多細節,libevent就夠了? – 2010-04-13 01:04:00

+0

這是一本關於維護者之一libevent的好書:http://www.wangafu.net/~nickm/libevent-book/ – 2010-06-19 05:40:03