1. 程式人生 > >多程序單執行緒模型與單程序多執行緒模型之爭

多程序單執行緒模型與單程序多執行緒模型之爭

伺服器,事件

多程序單執行緒模型典型代表: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