楔子
似乎有人不知道nodejs是支持多核的贱除?v0.10 Cluster可以搭建nodejs多核服務兴蒸。v0.12重寫了Cluster,據(jù)說提升了非常大的性能采桃。
服務器,事件
多進程單線程模型典型代表:nginx
單進程多線程模型典型代表:memcached
另外redis, mongodb也可以說是走的“多進程單線程那鹚穑”模型(集群)普办,只不過作為數(shù)據(jù)庫服務器,需要進行寫保護徘钥,只提供了讀同步衔蹲。
原因很簡單,因為服務器的發(fā)展大部分都是歸功于Linux Unix呈础,而不是Windows舆驶。
Linux內(nèi)核提供的epoll為開發(fā)服務器提供了很大的便利,libevent和libev都是對epoll的封裝而钞,nginx自己實現(xiàn)了對epoll的封裝沙廉。
libevent和libev都是知名的Linux系統(tǒng)C事件驅動編程框架。
我沒說錯的話臼节,nodejs是建立在libev基礎上撬陵。
memcached也依賴libevent。
所以网缝,nginx在Windows上不像Linux快是有很大原因的巨税。
模型,模型途凫,多進程單線程 單進程多線程
-
多進程單線程
master進程管理worker進程:
- 接收來自外界的信號
- 向各worker進程發(fā)送信號
- 監(jiān)控woker進程的運行狀態(tài)
- 當woker進程退出后(異常情況下)垢夹,會自動重新啟動新的woker進程
友情提示:nodejs屬于這一種好不好溢吻,不是只能單核
-
單進程多線程
主線程負責監(jiān)聽客戶端的連接請求维费,workers線程負責處理已經(jīng)建立好的連接的讀寫等事件
單進程多線程肯定比多進程單線程快一些
多進程單線程與單進程多線程的目的都是想盡可能的利用CPU果元,減少CPU的空閑時間,特別是多核環(huán)境犀盟。
他們在實際運行中而晒,所利用的CPU工作數(shù)應該都是相同的。也就是說阅畴,你有4核倡怎,在某個時刻要么是CPU同時在4個進程做任務(多進程單線程),要么是CPU同時在4個線程上做任務(單進程多線程)贱枣。
不過监署,單進程多線程肯定比多進程單線程快一些。
這是因為纽哥,多進程單線程的CPU切換钠乏,是從一個進程到另一個進程,而單進程多線程的CPU切換則只在一個進程內(nèi)春塌,每個進程|線程都有自己的上下文堆棧保存晓避,進程間的切換消耗更大一些。
這就好比是只壳,多進程單線程是在4個函數(shù)中切換俏拱,各自擁有自己的變量;單進程多線程在1個函數(shù)中的4個子函數(shù)切換吼句,擁有相同的全局變量锅必。
但是,沒有你想象的“快幾倍”惕艳。
副作用况毅,副作用,單進程多線程肯定有其不利的一面
我一直提過副作用尔艇。
如果你仔細看多進程單線程的圖尔许,就應該明白,這種模型提供了一種保護機制终娃。
當其中一個進程內(nèi)部讀取錯誤味廊,master可以讓ta重啟。這使得你的服務器在表面上并沒有感到“曾經(jīng)崩潰”棠耕。
對于master余佛,完全不涉及服務器的業(yè)務,使得ta能被安全隔離窍荧。
再來看單進程多線程辉巡。
問題很明顯,只有一個進程蕊退,一旦其中出現(xiàn)一個錯誤郊楣,整個進程都有可能掛掉憔恳。你當然可以為ta編寫一個“守護程序”來重啟,但是重啟期間净蚤,你的服務器是真的“掛掉了”钥组。
另外,編寫單進程多線程這樣的服務器今瀑,在代碼上非常容易出錯程梦,而且難以控制代碼的穩(wěn)定性,有很多你難以琢磨的bug在等著你橘荠,因為有太多的鎖屿附,太多的全局變量需要處理,這也是函數(shù)式“純函數(shù)”所反對的哥童。
nodejs不能CPU密集處理拿撩?
你覺得ruby,python如蚜,php就能密集處理压恒?
有人說:java, c#。
拜托错邦,如果你真的想要密集處理探赫,請使用C C++。(我個人只會用C)你見過哪個數(shù)據(jù)庫服務器是java c#寫的撬呢?
而現(xiàn)在伦吠,我覺得Rust lang是一個好的方向:
- 面向操作系統(tǒng)編程
- 從語言層面上提供并發(fā)
- 自詡C++的替代者
- 將會重寫firefox
- Mozilla開發(fā)
- Javascript的作者Brendan Eich是編寫者之一
- 類似javascript的語法和編寫體驗
而且我已經(jīng)開始憧憬未來使用nodejs + Rust開發(fā)服務器體驗的場景。