多進程單線程模型與單進程多線程模型之爭

服務器,事件

多進程單線程模型典型代表:nginx
單進程多線程模型典型代表:memcached

另外redis, mongodb也可以說是走的“多進程單線程模”模型(集羣),只不過作爲數據庫服務器,需要進行寫保護,只提供了讀同步。

原因很簡單,因爲服務器的發展大部分都是歸功於Linux Unix,而不是Windows。

Linux內核提供的epoll爲開發服務器提供了很大的便利,libevent和libev都是對epoll的封裝,nginx自己實現了對epoll的封裝。

libevent和libev都是知名的Linux系統C事件驅動編程框架。

我沒說錯的話,nodejs是建立在libev基礎上。

memcached也依賴libevent。

所以,nginx在Windows上不像Linux快是有很大原因的。

模型,模型,多進程單線程 單進程多線程

  • 多進程單線程

    master進程管理worker進程:

    • 接收來自外界的信號
    • 向各worker進程發送信號
    • 監控woker進程的運行狀態
    • 當woker進程退出後(異常情況下),會自動重新啓動新的woker進程

    友情提示:nodejs屬於這一種好不好,不是隻能單核

單進程多線程
單進程多線程
  • 單進程多線程

    主線程負責監聽客戶端的連接請求,workers線程負責處理已經建立好的連接的讀寫等事件

單進程多線程
單進程多線程

單進程多線程肯定比多進程單線程快一些

多進程單線程單進程多線程的目的都是想儘可能的利用CPU,減少CPU的空閒時間,特別是多核環境。

他們在實際運行中,所利用的CPU工作數應該都是相同的。也就是說,你有4核,在某個時刻要麼是CPU同時在4個進程做任務(多進程單線程),要麼是CPU同時在4個線程上做任務(單進程多線程)。

不過,單進程多線程肯定比多進程單線程快一些。

這是因爲,多進程單線程的CPU切換,是從一個進程到另一個進程,而單進程多線程的CPU切換則只在一個進程內,每個進程|線程都有自己的上下文堆棧保存,進程間的切換消耗更大一些。

這就好比是,多進程單線程是在4個函數中切換,各自擁有自己的變量;單進程多線程在1個函數中的4個子函數切換,擁有相同的全局變量。

但是,沒有你想象的“快幾倍”。

副作用,副作用,單進程多線程肯定有其不利的一面

我一直提過副作用。

如果你仔細看多進程單線程的圖,就應該明白,這種模型提供了一種保護機制。

當其中一個進程內部讀取錯誤,master可以讓ta重啓。這使得你的服務器在表面上並沒有感到“曾經崩潰”。

對於master,完全不涉及服務器的業務,使得ta能被安全隔離。

再來看單進程多線程

問題很明顯,只有一個進程,一旦其中出現一個錯誤,整個進程都有可能掛掉。你當然可以爲ta編寫一個“守護程序”來重啓,但是重啓期間,你的服務器是真的“掛掉了”。

另外,編寫單進程多線程這樣的服務器,在代碼上非常容易出錯,而且難以控制代碼的穩定性,有很多你難以琢磨的bug在等着你,因爲有太多的鎖,太多的全局變量需要處理,這也是函數式“純函數”所反對的。

nodejs不能CPU密集處理?

你覺得ruby,python,php就能密集處理?

有人說:java, c#。

拜託,如果你真的想要密集處理,請使用C C++。(我個人只會用C)你見過哪個數據庫服務器是java c#寫的?

而現在,我覺得Rust lang是一個好的方向:

  • 面向操作系統編程
  • 從語言層面上提供併發
  • 自詡C++的替代者
  • 將會重寫firefox
  • Mozilla開發
  • Javascript的作者Brendan Eich是編寫者之一
  • 類似javascript的語法和編寫體驗

而且我已經開始憧憬未來使用nodejs + Rust開發服務器體驗的場景。



原文鏈接:http://www.jianshu.com/p/c61a7746d139
發佈了77 篇原創文章 · 獲贊 189 · 訪問量 101萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章