關于Node.js語言的討論
本文是從 Node on nails! 這篇文章翻譯而來。
在開始敘述這篇文章之前,我要非常清楚和明確的聲明:“我并不是在鼓勵你放棄 NodeJS 或轉向 Java”。
我一直參與在這種爭論中。在我的編程界的朋友中一直存在著一種誤解,他們認為 NodeJS 語言是將來的趨勢。我對 Javascript 是百分百的喜愛(不是自吹,我有一段時間曾被認為是 Javascript 專家,我寫了很多喜歡 js 的文章);關于 Javascript 閉包的優美,原型模式編程風格的優勢,我是毫無質疑。但是,如果把 Javascript 放到后臺,這就完全是另外一種情況了。
每當我看到有人用一些重要的技術指標對 NodeJS 進行測評并宣稱NodeJS 是世界上最快的語言時,我都會覺得好笑。(你只要用谷歌搜一下 NodeJS vs *你能想到的任何東西*,你就會找到像這樣, 這樣, 和 這樣的東西。)
撇開我的質疑,NodeJS 的語言模式還是值得關注的,但我會在我的產品中使用它嗎?我的問題就在這。我在使用 NodeJS 的過程中發現了一些非常嚴重的問題;給人的感覺相當的糟。我必須寫一個完整的 HTTP 客戶包來支持 Multipart 方式傳送(現在這個包就是人們所知的 Reston),這樣我才能把文件發送到 Amazon S3 服務和其它一些 REST 服務里(當時沒有任何支持 HTTP Multipart 傳送的組件,HTTPS 也有問題,它折騰的我異常痛苦),總而言之,我需要向讀者們說下面幾個觀點:
◆ 并不是所有的 web 應用程序都需要大量的連接,你并不是每天都在開發一個聊天系統或一個 comet 系統。NodeJS 對處理某些事情很有優勢,我們可以用到它。如果你是讓我去在一個 IRC 服務器上開發一個基于 websocket 的聊天系統,我會推薦 NodeJS;但,如果你是讓我去把郵件從你的帳號中取出然后存到 RDBMS 或 NOSQL 數據庫中,那我就需要思量了。
◆ 技術架構選擇很重要!接受它!運用它!我看到有些人選擇了錯誤的技術路線(然后就炫耀說使用了 NodeJS),然后又發現了更好的方法來實現他的任務,于是又放棄了 NodeJS。
◆ 如果談論起事件為基礎的代碼實現和其可讀性,我相信幾乎每個人都會同意:回調式的代碼通常比正常流程形式的代碼更顯得混亂。
◆ 靜態類型的語言比動態類型的語言更具有優勢。如果你不了解編譯器的內部工作原理,就不要理會這一條了。
我的經驗已足夠用來做一次測評的了。我有一臺常見的中等性能的機器(3G 內存,雙核處理器),做為對比,我會直接使用 Java NIO 來處理 HTTP 請求,以“hello world”做為響應;同樣的過程用 NodeJS 實現一次。
NodeJS 代碼非常的直接。我使用的版本是 Node 0.4.9。請注意,這個操作依賴于’http’模塊,因此又依賴于’net’,’stream’等模塊。這些都是 NodeJS 的基本功能模塊(我沒有做任何特別的事情),它們依賴 V8 的 JIT 來實現高速的運行。
在 Java 上,我使用 Java 的 NIP 和 selector 通道來實現 NodeJS 上的相同效果(單線程事件分發)。代碼如預期中的一樣,有點長,因為要做循環處理。我盡量把所有的代碼都放到同一個文件里,所以,代碼沒有做模塊化等優化。就是這兩個文件:Runner.java 和core.SocketSelectorCore.java。我使用了 HashMaps,字符串的 split,indexOf 等方法來實現基本的 HTTP 頭信息的分析,以此模擬一個普通的請求流程(讀,分析,回應循環)。我使用的方法并不是很高效,但一般的時候這些方法都不是問題。
現在使用“node test.js”來啟動 NodeJS,使用 Apache Benchmark (ab -c 1000 -n 100000),1000的并發量[細節信息],大概是每秒鐘4-5千個請求的壓力運行三次。
在拿我寫的 Java NIO 的程序測試之前,我需要提醒大家幾個事情。Java 是一個野獸,你有一大堆的選擇參數來調控 JVM 的垃圾堆棧大小。在我的測試中,我使用 JVM 運行參數是“java -server -XX:+PrintCompilation -XX:+UseConcMarkSweepGC Runner”。請注意,我使用的是 verbose 模式的 JIT 編譯,這樣我就能知道 JVM 已經初始化完畢,可以開始測試了;我還改變了 GC 的方法(我試了各種方法,但看起來這個方法***)。當 JVM 完全啟動編譯后,我運行了相同的 Apache Benchmarks [細節信息]測試,Java 能處理每秒鐘8千-8千5百的請求。
我嘗試了不同的 JVM 堆的大小和一些其它的參數;結果非常的有趣。在我的機器上,我一直能達到每秒6千的處理能力。降低并發量(-c 100) ,處理能力能達到11000/s。如果你仔細看,你會發現,相對于 NodeJS,我在請求里封裝了更多的字節,但這并沒有影響 Java 的處理能力。得到了這些數據后,我還使用 JRuby,用它那神奇的語法寫了一個很粗燥的代碼。對 JRuby 上一些參數的微調,用這個很簡單的程序,我仍然能得到每秒4000-4500請求的處理能力。
現在,剩下的問題就是,我為什么要做這些,這些說明了什么?我想答案是相當明白。從個人的角度,我喜歡 Javascript 和 NodeJS,但我不接受人們說的“NodeJS 能做X但Y語言做不到“的言論。我認為把 Java 或 PHP 或其它語言跟 NodeJS 進行比較的行為是愚蠢的。Java 的 JIT 相當的先進,而 Google 也把 V8 發展到了一個新的高度。像 Netty NIO 和 Mina 這樣的框架已經存在很久了,只是因為 Java 的古怪的語法,對內存的貪婪,以及學習曲線,才沒有引起人們的注意。我只是要破除“NodeJS 因為它的異步特征能處理更多的連接,能讓你寫回調風格的代碼,也就是能寫出更好的代碼”的謬論。我的答案相當的簡單:“使用 Java 寫核心代碼,用 JRuby 或 Scala 的優美語法封裝,你會得到一個更好的處理事件驅動系統的方法”。
原文:http://www.aqee.net/node-on-nails/
【編輯推薦】