NodeJS,我對“高、高、非”的一些看法


·眾所周知

     NodeJS三大神器"事件驅動,V8,回調函數"。

·事件驅動,故名思議:等快遞和收快遞區別。NodeJS將原先大牛們掌握的神神秘秘的EPOLL走向大眾化,這點是最大的貢獻。當然事件驅動最早最有發言權的還是FLASH擁護者,在那個學校只教授順序編程的年代里,一些廣為流傳的FLASH作品都源自事件驅動。

·V8:初聞該名比較深奧。網上有不少介紹不再累述,個人理解快在JIT和HASH定位對象上,跳過了CLASS代碼。

·事件回調:這些年比較流行的風格,熟悉之后如沐清風,不熟悉的時候死活想不明白。

僅接着,圍繞着三項,無論是官方還是民間立即給NodeJS貼上了高性能、高並發、非阻塞I/O的標簽。一篇繁榮景象的面前,要想真正將此落地,仍然有許多功課需要完成。

·最大的硬傷"單線程"

     NodeJS有句話就"除了代碼,所有一切都是並行執行的"。這句話乍一看不是很明白,下面這個例子之后,

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+多線程,當然這前提得要有足夠時間思考,因為這個水非常深,並且要步步為營。在沒有強大的技術基礎上,還是推薦下面一些技巧,希望對大家有所借鑒。

  1. 首先,充分評估要實現的功能,如果業務量少的阻塞,可以借fork的力(child_process模塊)。
  2. 當你是一個服務端,如果有點良心的話,把settimeout留好,別外面人給拖死。寫代碼的都不容易。
  3. 當你是一個客戶端,記得保護好自己,要設超時,NodeJS的http沒有現成的timeout事件和模塊,這個得要重寫socket和streaming模塊,很麻煩。
  4. 針對短連接,調優操作系統TIME_WAIT參數的CD時間。並且棄用Fork,想盡辦法優化自身業務邏輯。

·萬事不離"能量守恆定律"

     沒有絕對的高性能服務器,就像世界上沒有永動機一樣,開門關窗、開窗關門。C/JAVA的Thread是以犧牲CPU為交換代價,Node的事件已自我承擔單線程風險為代價。把復雜的運算成本留給誰,這是值得認真思考的一件事情。

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM