多程序單執行緒模型與單程序多執行緒模型之爭
伺服器,事件
多程序單執行緒模型典型代表: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個函式中切換,各自擁有自己的變數;單程序多執行緒
但是,沒有你想象的“快幾倍”。
副作用,副作用,單程序多執行緒肯定有其不利的一面
我一直提過副作用。
如果你仔細看多程序單執行緒的圖,就應該明白,這種模型提供了一種保護機制。
當其中一個程序內部讀取錯誤,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