·衆所周知 javascript
NodeJS三大神器"事件驅動,V8,回調函數"。 java
·事件驅動,故名思議:等快遞和收快遞區別。NodeJS將原先大牛們掌握的神神祕祕的EPOLL走向大衆化,這點是最大的貢獻。固然事件驅動最先最有發言權的仍是FLASH擁護者,在那個學校只教授順序編程的年代裏,一些廣爲流傳的FLASH做品都源自事件驅動。 編程
·V8:初聞該名比較深奧。網上有很多介紹再也不累述,我的理解快在JIT和HASH定位對象上,跳過了CLASS代碼。 服務器
·事件回調:這些年比較流行的風格,熟悉以後如沐清風,不熟悉的時候死活想不明白。 多線程
僅接着,圍繞着三項,不管是官方仍是民間當即給NodeJS貼上了高性能、高併發、非阻塞I/O的標籤。一篇繁榮景象的面前,要想真正將此落地,仍然有許多功課須要完成。 併發
·最大的硬傷"單線程" 異步
NodeJS有句話就"除了代碼,全部一切都是並行執行的"。這句話乍一看不是很明白,下面這個例子以後, socket
req.on('end',function(){ console.log(j+":"+body); // sleep(11); //BLOCK /* //FORK exec("systeminfo",function(err,stdot,stderr){ res.end("aa"+'\n'); }); */ j++; res.write("ccc"+"\n"); });
就會發現若是出現了要想完成SLEEP這件事,光靠Node自己一個進程一個線程根本不可能實現。但在其餘高級語言C/JAVA中,SLEEP並非一件什麼大事,多起一個Thread就解決了。Node要想實現,只可能再Fork一個進程來分擔老爹進程的活。因此,市面上所謂的Node多線程模塊都是一種曲線救國,其實是多進程,包括之後能不能火起來的H5-WebWorker。因此,批註中的取systeminfo,這個比較耗時的動做也只能依靠Fork來繞開,已達到表面上的高併發高性能。 函數
那是否是經過神器"事件回調就能繞開"了呢?答案也是否認的,即使是在單線程模式下最接近異步調用的eventproxy也沒法完全解決這一難題。以下代碼,但這不妨礙eventproxy成爲一件大衆佳做。高併發
function sleep(milliSeconds) { var startTime = new Date().getTime(); while (new Date().getTime() < startTime + milliSeconds); } function test300(obj){ sleep(2000); obj.trigger("v3",300); } var EventProxy = require("eventproxy").EventProxy; var obj = new EventProxy(); var counter = 0; var add= function (v1, v2, v3){ console.log(v1+v2+v3+''); }; obj.assign("v1", "v2", "v3", add); obj.trigger("v1",100); test300(obj); obj.trigger("v2",200); console.log("I'm Done");
不少時候,有人甚至把NodeJS這一特性做爲賣點,我的絕對這個賣點用很差就會啃人,若是真要說賣點,卻是能夠往業務邏輯可讀性上去扯開。可是事件回調又給代碼可讀性脫了很多後退。因此,如今想一想老外的那句話真是一語中的,絕對算是很是負責的一句話。
·若是要作到"高、高、非"有辦法嗎?
老實說,就官網API來講難度真是不小,不少的例子太過理想化了。因此多少是要藉助其餘高級語言的輔助,其中取巧的方法就是EPOLL+多線程,固然這前提得要有足夠時間思考,由於這個水很是深,而且要步步爲營。在沒有強大的技術基礎上,仍是推薦下面一些技巧,但願對你們有所借鑑。
·萬事不離"能量守恆定律"
沒有絕對的高性能服務器,就像世界上沒有永動機同樣,開門關窗、開窗關門。C/JAVA的Thread是以犧牲CPU爲交換代價,Node的事件已自我承擔單線程風險爲代價。把複雜的運算成本留給誰,這是值得認真思考的一件事情。