前言:
身邊越來越多的同事談論Nodejs,談其異步IO、事件回調(diào)、前后臺統(tǒng)一一門語言,創(chuàng)業(yè)的朋友的第一個創(chuàng)業(yè)項目也選擇了Nodejs,期望能夠使用一種語言節(jié)省成本快速完成需求開發(fā)。與其他項目組的同事聊項目選型Java時被他們嘲笑了一把,怎么這么不與時俱進怎么還在用Java。而且發(fā)現(xiàn),越來越多的前端同事通過Nodejs輕松上手后端功能開發(fā),作為后端開發(fā)工程師倍感壓力。
借新項目的機會系統(tǒng)了解了下Nodejs的知識體系,本文對了解到的Nodejs技術作了總結,同時將其與Java的相關技術進行了總結對比,為其他考慮兩種語言選型的架構師提供選型的決策依據(jù)。為了避免爭議,本文避免對選型語言的推薦,也不對未來的發(fā)展趨勢做出預測。
語言背景分析:
簡單對兩門語言進行“拼爹”對比,發(fā)現(xiàn)有技術深度的事情還是博士比較擅長,計算機專業(yè)的技術又未必是計算機專業(yè)的人貢獻:
Nodejs
| Java
|
Ryan Dahl,非科班出身,數(shù)學系讀博士
2009年的2月開始開發(fā)Node,年底發(fā)表關于Node.js的演講
2010年由創(chuàng)業(yè)公司Joyent贊助開發(fā)
2013年更新緩慢、活躍度降低,糾結于穩(wěn)定內(nèi)核及新特性開發(fā)
2014年8月幾個重要core contributor發(fā)起組織(io.js前身),此后高速發(fā)展,新功能激進、高速版本迭代、問題反饋快速回復解決,2015年5月Node.js項目和io.js項目都將加入Node.js基金會,io.js繼續(xù)發(fā)展的同時進行合并,Nodejs的下一個版本將跨1.0直接到2.0
| 詹姆斯·高斯林,卡內(nèi)基·梅隆大學計算機博士,編寫了多處理器版本的Unix操作系統(tǒng),是JAVA的創(chuàng)始人。
1996年1月,第一個JDK-JDK1.0誕生
1997年9月,JavaDeveloperConnection社區(qū)成員超過十萬
1998年2月,JDK1.1被下載超過2,000,000次
2009-04-20甲骨文74億美元收購Sun。取得Java的版權;
|
語言及SDK分析:
Nodejs選擇javascript語法導致了其靈活、面向過程、單進程單線程執(zhí)行的基本特性。然而得意其語言的靈活性,一些面向對象的特征也可以通過邏輯代碼實現(xiàn),但受阻于ECMAScript的發(fā)展速度,整體上Nodejs向企業(yè)級應用語法轉型還暫時較慢。Nodejs主打的異步IO事件回調(diào)使其更適合服務器的編程,其單進程單線程的特質使得開發(fā)變得簡單。得意與社區(qū)的活躍語言處于高速發(fā)展、SDK不斷地發(fā)展穩(wěn)定豐富。
相比之下,Java是面向對象的具備了面向對象的全部特征,經(jīng)歷了20年的發(fā)展沉淀越發(fā)的強大、穩(wěn)健。與Nodejs相比Java是個在各個領域作精作深的技術巨人,然而也正因如此,學習Java的成本要比Nodejs高很大一個臺階,每一個小的技術方面都能找到很厚的一本書來。面對異步IO事件回調(diào)的新技術Java也在其新的SDK中提供支持與時俱進,相關Java的開源項目也及時跟進。
對比項
| Nodejs
| Java
|
函數(shù)式編程
| 非常自由,可以調(diào)用、作為參數(shù)、作為返回值
支持高階函數(shù)、偏函數(shù)用法
| Java8中支持了Lambda表達式實現(xiàn)函數(shù)編程與時俱進
|
類、接口、抽象類
| 原生不支持,本身是面向過程的,可利用函數(shù)實現(xiàn)類的定義能力。
| 原生支持,面向對象語言基本能力,依賴接口編程降低耦合
|
封裝、繼承、多態(tài)
| 原生不支持
| 原生支持,面向對象語言基本能力
|
動態(tài)
| 需要重啟或者重新加載
| 依靠jvm的字節(jié)碼和內(nèi)存管理技術,可以實現(xiàn)動態(tài)編譯、動態(tài)鏈接、動態(tài)加載、動態(tài)變更替換、熱部署
|
異常
| 支持,由于異步IO事件回調(diào)導致異常捕獲較為復雜。V8不會優(yōu)化含有try/catch的函數(shù)又導致過多捕獲異常產(chǎn)生性能問題。
全局捕獲uncaughtException會丟失堆棧通常為時已晚。
Domain機制當前還不穩(wěn)定。
| 支持,相對更成熟完善些,單線程異常不影響其他線程。
|
算法與數(shù)據(jù)結構
| Node本身提供的較為簡單,但開源社區(qū)相關代碼高速發(fā)展中
| 比較穩(wěn)定完善
|
集合Set\Map\List
| api能力較弱,ECMAScript 6引入Set和Map,2015年6月計劃發(fā)布,還需腳本引擎開發(fā)支持
| 完善豐富的集合容器,支持各種并發(fā)場景、業(yè)務特殊算法場景
|
事件回調(diào)與異步IO
| 語言級別支持,Nodejs殺手锏能力。
監(jiān)聽器模式實現(xiàn)事件回調(diào),利用事件隊列解決雪崩問題
| 1.4版本開始提供NIO工具包實現(xiàn)同步非阻塞IO
|
進程、線程
| 單線程單進程模式,開發(fā)成本低。
| 支持多線程編程,支持并發(fā)控制,較為復雜,需要有并發(fā)開發(fā)經(jīng)驗
|
網(wǎng)絡編程、WEB開發(fā)
| 可以十分方便地搭建網(wǎng)絡服務器
| 提供的還是底層API能力,由各個開源項目實現(xiàn)強大而專業(yè)的網(wǎng)絡編程框架及WEB開發(fā)框架
|
組件模塊、分包分層
| package.json集合文件夾定義包,包內(nèi)部可定義多個模塊
| 通過package、類、ClassLoader、壓縮包實現(xiàn)多維度多層次的劃分和復用的能力
|
注解、反射、泛型
| 無
| 原生支持
|
擴展性
| 支持C/C++編寫的邏輯擴展
| 支持C/C++/及其他可被JVM執(zhí)行語言編寫的邏輯擴展
|
三方開源框架選型:
語言選型后面即框架選型,好的框架可以去除很多不必要的重復工作使項目輕松獲取強大的功能。當然三方開源框架的引入也帶來的相應的學習成本,同樣的,Nodejs框架由于發(fā)展時間相對較短學習成本相對較低,開發(fā)人員更容易了解到更多底層的實現(xiàn)源碼,但相對的部分框架容易出現(xiàn)穩(wěn)定性兼容性問題,加之NPM開發(fā)人員水平不一而又沒有很好的審核機制,選擇一些模塊(尤其是C/C++模塊)時需要慎重。Java三方開源框架大都已被大量企業(yè)大量使用、成熟穩(wěn)定,提供強大能力的同時作了很好的封裝分層,開發(fā)人員付出較高的學習成本后更多的是“傻瓜“式的使用。就WEB開發(fā)體系而言,兩者都可以找到很多可服用引入的開源框架。
對比項
| Nodejs
| Java
|
數(shù)據(jù)庫
| 針對不同數(shù)據(jù)庫類型引入不同的驅動模塊,Mongoose/reids/mysql
| 可以針對不同的數(shù)據(jù)庫引入不同的驅動模塊,也可以使用多個開源框架,降低數(shù)據(jù)庫使用成本、不同數(shù)據(jù)源的遷移成本:
|
MVC框架開發(fā)WEB
| Express/Koa:輕量靈活快速地搭建網(wǎng)站,支持多種模板,利用generatora解決了繁瑣的回調(diào)嵌套
| 相關框架均較為成熟可靠,典型的有:
|
前端模板
| EJS:強大易用,語法更接近前端語言。Jade語法更接近后端語言,功能更強大
| Velocity:基于java的模板引擎,阿里主流選擇,內(nèi)部進行了性能優(yōu)化,支撐住了淘寶天貓的大流量
|
Rest開發(fā)
| Restify:Rest應用框架,支持服務器端和客戶端,專注Rest服務
| JAX-RS:提供了一些標注將一個資源類、一個POJO Java類封裝為Web資源。
|
Web Socket
| Socket.IO:跨平臺,多種連接方式自動切換,做即時通訊方面的開發(fā)很方便
| Netty:異步的、事件驅動的網(wǎng)絡應用程序框架和工具包
|
日志管理
| Log4js:簡單易用,winston:功能更強大,稍復雜
| Log4j:輸出定制、日志級別格式控制。Slf4j:簡單統(tǒng)一的日志接口
|
HTTP調(diào)用
| Request:建立各種HTTP請求,支持授權驗證,其實功能還是非常多的,基本滿足絕大部分需求。
| HttpClient:Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包
|
異步流程控制
| Async:使異步流程同步化。Q是另外一種非常不錯的選擇,它是實現(xiàn)了promises接口。
| asyn4j:異步方法調(diào)用框架,基于消費者與生產(chǎn)者模式。包括了異步方法執(zhí)行,異步回調(diào)執(zhí)行,異步工作緩存模塊.支持Spring。
|
定時任務
| Cron:小巧的定時任務管理模塊。Later功能強大但稍微復雜
| Quartz:可以用來創(chuàng)建簡單或為運行上萬個jobs這樣復雜的程序,讓作業(yè)變得易用管理
|
其他框架
| 社區(qū)活躍,更新非???,但也容易存在不穩(wěn)定、不兼容的風險。
Npm模塊的開發(fā)人員水平不一,暫時只能依靠口碑、測試文檔等條件選型
| 各種場景均有很多成熟穩(wěn)定開源框架可供選擇,公司內(nèi)部通常也有自己的成熟項目
|
產(chǎn)品化分析:
就產(chǎn)品化而言,Nodejs雖然在各個方面都有建設,但相對Java還有很多需要繼續(xù)完善發(fā)展的地方,如系統(tǒng)監(jiān)控和性能分析領域還不如Java體系那么完善,受限于單進程單線程模式穩(wěn)定性部署方面還不如Java那么靈活,靈活的腳本語言加上Nodejs發(fā)展時間相對較短使得系統(tǒng)的安全性還需要經(jīng)受更多的考驗。同時,前后端代碼都可以使用到js并同時保存在一個開發(fā)分支時,單純的依賴目錄去區(qū)分前后端代碼,容易造成前后端代碼的混淆,相對不夠清晰。但相信爭議和問題都是暫時的,高速發(fā)展的Nodejs會逐步完善完美。
對比項
| Nodejs
| Java
|
編碼規(guī)范
| JSLint/JSHint:定義代碼格式規(guī)范的規(guī)則,統(tǒng)一編碼
| CheckStyle/FindBug/Code formatter:比較完善,支持持續(xù)集成
|
包管理、構建
| NPM:Nodejs的包管理器,模塊庫發(fā)展是十分神速和活躍
| MAVEN:一個項目管理和構建自動化工具,包含了一個項目對象模型、一組標準集合、一個項目生命周期、一個依賴管理系統(tǒng)、插件,方便、擴展性好、功能強大
|
部署
| 腳本方式啟停進程進行部署
| WEB項目利用Maven可以打包成一個war包,直接部署到容器的指定目錄即可。
|
系統(tǒng)監(jiān)控
| 但針對Nodejs的監(jiān)控技術還是比較缺乏的,資料也比較缺乏
| JVM提供虛擬機各項指標的監(jiān)控接口,包括C++和Java的,基于此類接口實現(xiàn)了很多成熟的監(jiān)控工具,互聯(lián)網(wǎng)公司內(nèi)將很多監(jiān)控能力WEB化
|
性能分析
| 內(nèi)存快照分析:node-heapdump/node-memwatch
| 基于JVM的工具API實現(xiàn)有多種性能分析工具,可以分析CPU耗時分布、CPU調(diào)用鏈、CPU熱點、內(nèi)存分布、內(nèi)存熱點、線程阻塞等等。
|
穩(wěn)定性
| 受限于單進程單線程的設計,穩(wěn)定性需要引入多進程來解決,限制較大,相對比較耗費資源
| 傳統(tǒng)的多線程、多進程、多機多機房機制,靈活選擇部署,穩(wěn)定性已經(jīng)歷過線上的長期考驗
|
安全性
| 腳本語言的安全性較弱加上Nodejs的語法靈活性導致編碼時較容易出現(xiàn)安全問題,已成立Node安全項目有針對性的分析解決Nodejs的安全問題。
| 相對腳本語言安全性較強,漏洞經(jīng)過多年分析與解決
|
執(zhí)行引擎分析:
在瀏覽器方面V8引擎大名鼎鼎贊不絕口,這也是Nodejs選型V8這個最快的Javascript執(zhí)行引擎的原因。然而另一方面,V8引擎專門針對瀏覽器的設計也嚴重限制了Nodejs在服務器領域的大有作為,仿佛帶著手鏈腳鏈在高速奔跑。因V8引擎的創(chuàng)始人和技術都是來自Java虛擬機,使用了部分Java虛擬機技術適配瀏覽器業(yè)務實現(xiàn),所有相比之下Java虛擬機更加的成熟完善,也必然相對的復雜沉重。
對比項
| Nodejs
| Java
|
引擎概述
| V8:最快的JavaScript虛擬機,參考JVM部分核心技術實現(xiàn),針對瀏覽器需求場景而專門設計優(yōu)化
| JVM:成熟穩(wěn)定完善的虛擬機技術及體系,各個內(nèi)部模塊算法等都經(jīng)過深入研究形成專業(yè)領域,V8的創(chuàng)始人是原SUN的技術人員
|
內(nèi)存限制
| V8專為瀏覽器設計,最大內(nèi)存占用:64位1.4GB,32位0.7GB,新生代分布對應為最大32M和16M(限制可打開,容易造成延遲,不推薦)
| 可以結合系統(tǒng)的內(nèi)存情況可以按需要設置,并且可以根據(jù)業(yè)務對內(nèi)存的需求靈活設置調(diào)優(yōu)。
|
垃圾回收
| 模仿JVM的分代回收。新生代晉升條件相對固定,復制回收。老生代標記清除回收(壓縮解決碎片問題)
| 普遍分代回收,有多種垃圾回收算法可供選擇,每個回收算法有多種參數(shù)可以配置調(diào)優(yōu),持續(xù)發(fā)展更新。
|
內(nèi)存監(jiān)控分析
| process.memoryUsage查看內(nèi)存概況,os模塊的totalmem()和freemem()查詢系統(tǒng)內(nèi)存使用
| JVM提供C++和Java的接口可以查詢詳細的JVM內(nèi)存及系統(tǒng)內(nèi)存信息
|
跨平臺、可移植
| 暫時只能支撐到Chrome瀏覽器支撐得了的平臺
| 任何虛擬機支撐的平臺,更為廣泛穩(wěn)定
|
擴展性
| 為瀏覽器設計,擴展性相對較差,體系還不夠完善
| 技術體系比較深,提供多種接口方便三方擴展開發(fā)
|
其他一些對比:
其他一些簡單對比如下:
領域
| 對比項
| Nodejs
| Java
|
開發(fā)工具
| IDE
| WebStorm
| Eclipse
|
測試技術
| 單元測試
| Mocha/Karma/Jasmine
| Junit/TestNG/jMock
|
應用場景
| 場景
| 服務器編程,擅長高并發(fā)IO密集型程序項目
| 服務器編程、大數(shù)據(jù)、企業(yè)開發(fā)、android
|
開發(fā)者
| 來源
| 部分是向后臺開發(fā)試水的前臺人員,部分是被異步I/O吸引的后臺人員
| 大部分還是后臺開發(fā)人員
|
結束:
Nodejs的異步IO、事件回調(diào)雖是殺手锏能力,但其他程序開發(fā)語言也都有相應的跟進支持,但Node成功將前后端統(tǒng)一一門語言開發(fā),這絕對是無人能及,吸引了大批的開發(fā)者加入。得益但又受限于V8引擎,其發(fā)展還帶著包袱,但Nodejs還年輕還處在高速發(fā)展中,相信隨著IO.js與Node.js合并、越來越多的開發(fā)者進行共建,Node會越來越穩(wěn)定成熟。
相比之下Java是編程領域的巨人,20年的發(fā)展,越發(fā)的成熟穩(wěn)定,形成完善的體系完善的生態(tài),Android的流程再次將這門語言推到了巔峰,架構選型永遠是個重點選項。
https://as.h5con.cn/articles/54118?spm=5176.100239.blogcont118673.32.8NFfUv