Node.js真的無所不能?那些不適用的應(yīng)用領(lǐng)域分析
原創(chuàng)Node.js是一個(gè)服務(wù)器端JavaScript解釋器,底層采用的還是libevent;它的目標(biāo)是幫助程序員構(gòu)建高度可伸縮的應(yīng)用程序,目前對(duì)Node.js 的采用狀況,Node.js 官方站點(diǎn)有一些羅列,但是相當(dāng)不完整。如果你自己公司用到,也可以在 github 上提交自己的 pull-request 來更新這個(gè)文檔。
https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node
其實(shí)到今天為止,很少有哪些大的互聯(lián)網(wǎng)公司是和 Node.js 無關(guān)的。LinkedIn,Yahho,Paypal, eBay, Walmart 都在將既有的系統(tǒng)向 Node.js 遷移(https://www.quora.com/Node-js/What-companies-are-using-Node-js-in-production 翻墻看)。國(guó)內(nèi)的淘寶、網(wǎng)易、百度等也都有很多項(xiàng)目運(yùn)行在 Node.js 之上。
2011 年我開始接觸 Node.js 的時(shí)候,npmjs.org 上只有不到 3,000 個(gè) Node.js 的 packages,今天(2014-3-2)則有 61,897 個(gè),這個(gè)數(shù)字還在快速增長(zhǎng)中。
下面有兩個(gè)鏈接,第一個(gè)是在講 Walmart 這幾年為什么以及如何遷移到 Node.js 上;第二個(gè)則為 eBay 是如何從 Node.js 的懷疑者轉(zhuǎn)變?yōu)椴捎谜摺?/p>
《Announcing ql.io》 這篇文章的最后一段,列出了 eBay 為什么選擇 Node.js。
每天都有幾百個(gè)新的 packages 被發(fā)布到 npm 上,小到幾行代碼,大到萬行代碼的 Framework。一天有7百萬次的包下載(安裝到某臺(tái)電腦上),對(duì)于單一開發(fā)框架的社區(qū)來說,用沸騰的海洋來形容并不過分。
以下應(yīng)用領(lǐng)域和程序員不適合選擇Node.js:
- 計(jì)算密集型應(yīng)用。Javascript 的計(jì)算性能是很難和 C 語言代碼相比的。當(dāng)然,也有反例:http://onlinevillage.blogspot.jp/2011/03/is-javascript-is-faster-than-c.html,只不過不具有典型性。
- 需要精密控制內(nèi)存的分配和釋放的場(chǎng)景,如果用 Node.js 實(shí)現(xiàn) Redis 數(shù)據(jù)庫(kù),雖然程序會(huì)簡(jiǎn)單不少,但是 JVM 對(duì)內(nèi)存數(shù)據(jù)結(jié)構(gòu)的精密控制能力是比不了用 C 語言純手工打造的。
- 大量且需要頻繁通過 C Binding 調(diào)用 C library 的情況。這種場(chǎng)景下,往返參數(shù)的 Marshal/Unmarshal 的成本可能會(huì)大于 C Library 帶來的性能提升。
- 實(shí)時(shí)性要求很高的場(chǎng)景,例如:交換機(jī)或者工控機(jī)器人。這是因?yàn)樗型ㄟ^垃圾回收機(jī)制來管理內(nèi)存的系統(tǒng)都有可能在 GC 過程中產(chǎn)生停頓,從而影響響應(yīng)速度,而且很難優(yōu)化。
- 需要單一進(jìn)程控制大內(nèi)存的場(chǎng)景:v8 引擎的設(shè)計(jì)限制,在 32-bit下有 1GB 最大堆尺寸的限制,在 64-bit下是1.7GB。當(dāng)然,由于 node.js buffer 的分配不是在 v8 的堆上,因此可以超過此限制。這個(gè)限制可以通過向 v8 引擎?zhèn)鬟fmax_old_space_size 參數(shù)來超越,但是也會(huì)帶來 GC 的性能退化。這一問題在幾乎所有 GC Based 的系統(tǒng)下都存在。
- 不關(guān)心系統(tǒng)吞吐率或者不需要異步調(diào)用的場(chǎng)景:例如,自動(dòng)化腳本,這些腳本不需要關(guān)心多用戶并發(fā)訪問的性能消耗。用 Python 這樣的“膠水”語言寫起來會(huì)更簡(jiǎn)單。
- 某些非通用場(chǎng)景:例如 nginx 對(duì)于靜態(tài) web server 或者 反向代理的場(chǎng)景是特別設(shè)計(jì)的,這些場(chǎng)景中 nginx 的性能比 Node.js 要好。
- 強(qiáng)類型強(qiáng)迫癥:有些 Java 或者 .NET 過來的程序員會(huì)認(rèn)為只有強(qiáng)類型語言和嚴(yán)格定義的類型系統(tǒng)是專業(yè)化的象征,構(gòu)造這樣的系統(tǒng)是架構(gòu)師的使命,而動(dòng)態(tài)語言只是玩具,只能用來做 Demo 或者前端開發(fā)。
- 團(tuán)隊(duì)成員難以理解或者接受函數(shù)式編程:Javascript 本質(zhì)上更像函數(shù)式語言,有些程序員在理解和使用閉包、高階函數(shù)等概念時(shí)總是不能習(xí)慣,這個(gè)問題在國(guó)內(nèi)的開發(fā)團(tuán)隊(duì)中還挺普遍的。
- 回調(diào)式編程的不習(xí)慣:Node.js 的異步IO 大量依賴回調(diào)?;卣{(diào)讓程序的執(zhí)行出現(xiàn)了兩條路徑,出現(xiàn)故障時(shí)調(diào)用棧也很難理解。這對(duì)習(xí)慣了同步編程的程序員來說一開始確實(shí)是個(gè)坎。async, Q promise 等 package 可以緩解這個(gè)問題(在 ES6 的Generator 普及之前),不過這也帶來了更陡峭的學(xué)習(xí)曲線。一般情況下,需要半年到一年的習(xí)慣過程,當(dāng)然前提是多看,多寫。隨著越來越多的經(jīng)驗(yàn)分享,這個(gè)過程也在不斷地縮短。
除此之外的領(lǐng)域,或者沒有上述問題的,都都可以享受到 Node.js 帶來的生產(chǎn)力提升和穩(wěn)定的性能保障。
性能的爭(zhēng)議
不同開發(fā)環(huán)境間的性能對(duì)比從來都是有爭(zhēng)議的話題。我只能說,當(dāng)開發(fā) Web 或 網(wǎng)絡(luò)環(huán)境下的應(yīng)用時(shí),Node.js 靠以下幾個(gè)方面來避免出現(xiàn)不必要的性能問題:
- Chrome V8,一個(gè)可靠的優(yōu)秀的虛擬機(jī)(hidden classes 和 inline caching),讓 Javascript 的運(yùn)行速度進(jìn)入了第一陣營(yíng)(C++, Java, .NET)。
- 異步 IO 大大降低了線程數(shù)量,莫名其妙的死鎖和等待的概率被降低了很多。大部分場(chǎng)景不用去考慮并發(fā)和同步鎖,犯錯(cuò)誤的機(jī)會(huì)少。而在 Python 中,異步 IO 并不是標(biāo)準(zhǔn),并沒有被貫穿到所有 Package 中,因此應(yīng)用程序也就很難獲得一致的性能保障。
- 非常輕巧的“內(nèi)核”。Node.js 的模塊分為 Core Modules 和 Userland 兩部分。Core Modules 非常精簡(jiǎn),只包括 TCP, HTTP, DNS, File System, child processes 和其他一些模塊,這些網(wǎng)絡(luò)庫(kù)還只有異步版本。相對(duì)地,在 Userland 中卻有著海量的 Packages。開發(fā)應(yīng)用的時(shí)候,我們根據(jù)應(yīng)用的需求來組合 Userland 的 Packages,使得我們的應(yīng)用程序有機(jī)會(huì)在一個(gè)很低的資源消耗水平下運(yùn)行(在《Announcing ql.io》中指出,一臺(tái)開發(fā)服務(wù)器就可以支持 12 萬活躍連接,平均每個(gè)連接消耗 2k 內(nèi)存)。事實(shí)上,我開發(fā)的 WebSockte 應(yīng)用在 Raspberry Pi 下都可以支持幾百并發(fā)長(zhǎng)連接(WebSocket)。和那些動(dòng)輒上萬個(gè)類的企業(yè)開發(fā)框架相比,這是一個(gè)巨大的優(yōu)勢(shì)。這種方式降低了出現(xiàn)問題的概率、查找問題的成本以及減少部署成本。
對(duì) Javascript 的絕對(duì)性能的追求一直沒有停頓(例如, Mozilla 的 asm.js )。而 Node.js 則在絕對(duì)性能的基礎(chǔ)上,確保應(yīng)用程序可以獲得穩(wěn)定和可預(yù)測(cè)的性能保障( Benchmark 和實(shí)際的應(yīng)用運(yùn)行往往是兩回事)。
Node.js繼承了JavaScript 的靈活性,優(yōu)秀的JS庫(kù)應(yīng)當(dāng)如何選擇
可以在 npmjs.org 或者 google 上搜索關(guān)鍵詞。如果類似的返回很多,則看其被其他 package 依賴的數(shù)量有多少。上 github 上查看 starred 和 forks 的數(shù)量,讀 issues。
如果是“名人”(substack, visionmedia (TJ Holowaychuk), dominictarr, rvagg 等)寫的 Packages 自然會(huì)被加分。
最后是把 Git Repo. Clone 或者 Fork 下來, 閱讀且注釋他們的源代碼。這個(gè)過程也可以發(fā)現(xiàn)很多他們依賴的其他 Packages。這是一個(gè)蠻享受的過程,可以學(xué)到很多新知識(shí)和新的用法。
還有一些亂槍打鳥的方法:
- 在 Tweeter 上關(guān)注 @nodenpm,所有在 npm 上發(fā)布或者更新的 packages 都會(huì)在該 handle 上發(fā)布出來。在你的碎片時(shí)間沒事可以刷刷這個(gè),當(dāng)然你需要 APN 翻墻。
- 關(guān)注一些推薦和評(píng)論賬號(hào):@dailyjs,@echojs 等。
- Changelog 會(huì)提供不錯(cuò)的開源信息匯總,其中包括 Node.js、Javascript 和 npm 欄目。
- Hacker News 則不會(huì)讓你忽略軟件行業(yè)的一些“大事”或者新概念。
一個(gè)項(xiàng)目開始前的研究階段,我大約會(huì)瀏覽幾十個(gè) Packages,精讀其中的5 ~ 10個(gè)。開發(fā)過程中則根據(jù)需要還會(huì)不斷地發(fā)現(xiàn)和精讀一些,這些都被我計(jì)入了項(xiàng)目的成本。
"自由選擇,自己負(fù)責(zé)",在這個(gè)龐大的開發(fā)社區(qū)了不要指望有人能告訴你“標(biāo)準(zhǔn)答案”。每個(gè)人面臨的問題域和知識(shí)背景都不一樣,堅(jiān)持多看,多試,多思考,享受獲得新知識(shí)的過程比獲得“標(biāo)準(zhǔn)答案”更重要。
在眾多的成熟開發(fā)框架下為什么需要Node.js
在每一個(gè)特定的問題域,大家總是在嘗試找到最優(yōu)解。這個(gè)過程是沒有終結(jié)的,就想最終也會(huì)有其他框架代替 Node.js 一樣。
今天的 Web,是無數(shù)相互連接的 Web Services 組成的,這些連接的本質(zhì)是異步的。Node.js 天生異步的特性和這個(gè)場(chǎng)景的匹配度相對(duì)其他開發(fā)框架要更高,因此實(shí)現(xiàn)起來也更自然。
除此之外,Node.js 的設(shè)計(jì)基本原則遵循了 《Unix 的編程藝術(shù)》,參見 Isaac Z. Schlueter (前任 Node.js 的Gatekeeper,目前負(fù)責(zé) npm 的商業(yè)化) 的Blog: Unix Philosophy and Node.js。
npm 和 stream 就是上述哲學(xué)的產(chǎn)物。
npm
npm 是 Node.js 的包管理系統(tǒng)。包管理系統(tǒng)不是新東西,但是和 npm 的那些前輩和表兄弟不同的是:
- npm 直接集成在 Node.js 中,無需單獨(dú)安裝,發(fā)布,安裝 packages 非常簡(jiǎn)單。
- npmjs.org 提供一個(gè)統(tǒng)一的入口,你可以看到每個(gè) package 被哪些 packages 所依賴,你也可以一目了然地看到它依賴了誰,以及最近的下載次數(shù)。結(jié)合到 github 上的更新情況,基本上對(duì)一個(gè) package 的基本情況你都能了解到。
- 約定俗成的發(fā)布規(guī)范:一個(gè) git repo. 讓你可以直接找到源代碼;README.md 提供簡(jiǎn)要的說明讓消費(fèi)者能盡快用起來。
對(duì)于開發(fā)者來說,每一個(gè) package 就是一個(gè) "micro service",是最小重用單元。大部分的 package 只有幾百行代碼,甚至有些只有幾行代碼。這樣的重用粒度是在其他社區(qū)難以想象的。
在 Node.js 的應(yīng)用的開發(fā)過程中,編寫 “一口尺寸”(bite-size)的 module 是推薦的編程方式。這也很方便你把這些小 module 封裝為 package 分享到社區(qū)當(dāng)中,而不用擔(dān)心泄露“企業(yè)機(jī)密”。
npm 是每一個(gè) Noder 的 "home",也是每一個(gè) Node.js 應(yīng)用的系統(tǒng)架構(gòu)的一部分。
#p#
Stream
如果說,npm 提供了“開發(fā)時(shí)重用”的機(jī)制,那么 stream 的則提供了“運(yùn)行時(shí)”不同組件之間的“重用”機(jī)制。stream 概念和 unix 中的 stream 對(duì)應(yīng),應(yīng)用中的每一個(gè) component 則對(duì)應(yīng) unix 的 filter。下面舉一個(gè)實(shí)際的例子:
在某個(gè)應(yīng)用中,我需要一個(gè) API Server,它的客戶端包括 Web Browser,iOS App., 以及網(wǎng)絡(luò)中的其他 Server。Web Browser 和我們的 API Server 的通信基于 SockJS(當(dāng)然你也可以選擇 SocketIO,或者 Faye 等),它為瀏覽器兼容提供了適當(dāng)?shù)?“Fallback” 方案;對(duì)于 iOS App.來說,由于不需要考慮瀏覽器兼容,則采用基于標(biāo)準(zhǔn)的 RFC 6455 的純 WebSocket 通信協(xié)議,這樣實(shí)現(xiàn)起來更簡(jiǎn)單;而對(duì)于其他 Server 來說,局域網(wǎng)內(nèi)則用 TCP,互聯(lián)網(wǎng)上則用 TLS 來保證傳輸安全。
我在 Node.js 上是這么實(shí)現(xiàn)的:
- 利用 donde 構(gòu)建一個(gè)通信無關(guān)的 RPC Server 來提供 API 服務(wù)。
- 用 Node.js Core Modules 中的 tcp, tls 創(chuàng)建 TCP/TLS Server 并監(jiān)聽,用第三方的 SockJS 和 websocket-stream 分別創(chuàng)建 SockJS 和 WebSocket 的 Server 并監(jiān)聽。
- 當(dāng) Client 連接到不同的端口,在 Server 上就會(huì)創(chuàng)建基于該協(xié)議的 Commnucation Stream,然后創(chuàng)建一個(gè)新的 dnode 實(shí)例,得到一個(gè) dnode 的 Stream。最后將 Commnucation Stream 和 dnode Stream 像接水管一樣接到一起即可。
- net.createServer(function(connStream){
- dnodeStream = dnode({ func1: function(){} });
- connStream.pipe(dnodeStream).pipe connStream;
- });
考慮到在不穩(wěn)定的網(wǎng)絡(luò)環(huán)境下的自動(dòng)重連需求,也可以添加 reconnect。
不算你自己 RPC API 的實(shí)現(xiàn)邏輯,支持這么多的通信協(xié)議的 Server 框架只需要百十行代碼,還加上了一定程度的異常處理。
tcp, tls, SockJS,或者 reconnect 的開發(fā)者并不能確定“消費(fèi)者”是如何使用這些 Package 的,但是大家都支持 Stream 的接口,則讓自己的 Package 能夠被運(yùn)用到更多的場(chǎng)景。
進(jìn)一步,我們也可以多路復(fù)用一個(gè)底層的 Stream。我們把上面的例子再擴(kuò)展一下:
在既有的通信連接上(connStream),除了提供 RPC API 之外,還需要添加分布式的狀態(tài)同步功能,例如:通過 Scuttlebutt,完成 Client 與 Server 或 Server 與 Server 之間的常量數(shù)據(jù)自動(dòng)同步,而不用為這些功能設(shè)計(jì)新的 RPC API。通過 mux-demux ,可以復(fù)用既有的網(wǎng)絡(luò)通信 Stream(tcp, SockJS, Web Socket...),避免建立不必要的網(wǎng)絡(luò)連接。
Stream 是 Node.js 的核心概念之一,其接口和工作方式被廣泛地采用,為不同組件在運(yùn)行時(shí)相互通信提供了最基本的支持。
在 Node.js 中,如何使用 Stream 可以用一本書的容量來描述,不是因?yàn)?Stream 的概念有多復(fù)雜,而是因?yàn)槠浣M合方式非常豐富。
小結(jié)
三年前接觸 Node.js,并且學(xué)習(xí)和采用,主要原因是因?yàn)?Node.js 在解決當(dāng)今網(wǎng)絡(luò)應(yīng)用的問題時(shí),提供了高性能、高可靠和低功耗的方法。高性能、高可靠和低功耗,不是在于 Node.js 做了什么,而是在于 Node.js 不做什么。Node.js 和 Javascript 的概念,在 Java 或者其他開發(fā)框架中都能找到對(duì)應(yīng)的概念。但是 Node.js 僅保留了它認(rèn)為最重要的部分作為 Core Modules,其他都讓給了 User Land,這才是高性能、高可靠和低功耗的最本質(zhì)的保障。
隨著 Node.js 這三年的發(fā)展,今天使我浸淫其中的理由已經(jīng)不是之前的那些特點(diǎn)了。
npm 建立了一個(gè)“人人為我,我為人人”社區(qū),無論你是一個(gè)入門級(jí)的 Noder,還是一個(gè)多年的老兵,都在自覺或不自覺地從這個(gè)社區(qū)吸取營(yíng)養(yǎng),也在不斷地回饋社區(qū)。在使用 npm 的過程中,你會(huì)很自然地發(fā)現(xiàn),將自己的應(yīng)用切割為盡量小的 Modules,發(fā)布為公有的 Packages,配上一個(gè)簡(jiǎn)單扼要的 README.md,反而是最有效率的系統(tǒng)架構(gòu)方式。
Node.js 所遵循的 Unix 設(shè)計(jì)哲學(xué),又提供了最簡(jiǎn)單有效的復(fù)用規(guī)范。簡(jiǎn)單有效,才會(huì)被大家自覺采用,采用得越多,重用的可能性就更大。以Express 4.0 ( MEAN 架構(gòu)中的那個(gè) 'E' )為例,這么一個(gè)流行的 MVC Web Framework的核心代碼只有 2,600 多行(不算測(cè)試,中間件和例子,但是包括注釋)。
npm 和 github 一起,為今天的軟件生產(chǎn)提供了新的生產(chǎn)關(guān)系,這也是當(dāng)前 Node.js 超越其他社區(qū)的根本原因。不是單純的性能,也不僅僅是因?yàn)閯?dòng)態(tài)語言,甚至不是因?yàn)榇罅渴煜?Javascript 的前端程序員(和后端程序員相比,由于缺少系統(tǒng)性的思維,前端 Javascript 程序員掌握 Node.js 未必有多少優(yōu)勢(shì) ),而是以更加便捷的分享式開發(fā)為基礎(chǔ)的生產(chǎn)關(guān)系實(shí)實(shí)在在地提升了軟件生產(chǎn)力。
Node.js的駕馭能力
如果“復(fù)雜的后端程序” 等于 “龐大的繼承樹”,“強(qiáng)類型安全”,“精細(xì)的異常定義和處理”,那么 Node.js 當(dāng)然無法駕馭。因?yàn)?Node.js 和 Java, .NET 相比,是一顆獨(dú)立的“科技樹”。原型繼承、函數(shù)式編程、模塊系統(tǒng)、回調(diào)...,這些概念和編程方式對(duì)習(xí)慣了 Java 以及 .NET 的程序員來說不僅僅是不熟悉,甚至一開始會(huì)產(chǎn)生“不舒服的”感覺。
從我的體驗(yàn)來看(Basic->C->VB->Delphi->.NET->Node.js),這種不舒服更多地來自于之前對(duì)嚴(yán)謹(jǐn)?shù)念愋拖到y(tǒng)的信仰。原本所謂的“架構(gòu)師”,承擔(dān)著整個(gè)應(yīng)用或項(xiàng)目的類型系統(tǒng)的建設(shè)任務(wù),對(duì)任何破壞類型一致性的行為都會(huì)自然而然的產(chǎn)生抵觸情緒。要想掌握 Node.js,最好的方法是先從 Java, .NET 這顆“科技樹”上爬下來,清空自己,然后重新爬 Node.js 這棵樹。
程序員從 Java, .NET 可以學(xué)到面向?qū)ο蠛头盒瓦@些重用手段,而在 Node.js 的世界中,當(dāng)你接觸到大量來自于完全不同背景的程序員所編寫的 Packages 的時(shí)候,你也會(huì)意識(shí)到,不是每樣?xùn)|西都是“類”,重用也不一定都基于繼承。雖然有人試圖在 Node.js 中克隆之前自己熟悉的類型系統(tǒng),但是更多的程序員則在不斷嘗試更優(yōu)雅、簡(jiǎn)單的編寫方式。在 Node.js 的開發(fā)過程中,沒有所謂的“最佳實(shí)踐”,類似的問題總會(huì)有人嘗試不同的解決方法。對(duì)于一個(gè)勤于思考和反思的程序員,這是一個(gè)充滿樂趣的過程。反之,如果你的團(tuán)隊(duì)是由缺少獨(dú)立思考或者獨(dú)立解決問題的程序員組成的,那么 Node.js 確實(shí)不適合。你需要用強(qiáng)類型語言搭好一個(gè)受限的框架,然后讓體力型的隊(duì)友去填空。
我們公司只有兩個(gè)程序員,一個(gè)負(fù)責(zé) iOS 開發(fā),而我負(fù)責(zé)“復(fù)雜”后端程序和 Web Browser 開發(fā)。如果用 Java 或者 .NET 來開發(fā),完成同樣的功能需要至少三倍以上的人力。
Node.js能否統(tǒng)一前后端
完全統(tǒng)一既不可能,也沒必要。再說這個(gè)所謂的“統(tǒng)一”與其放到 Node.js 腦袋上,不如送給 Javascript,因?yàn)?Javascript 用到的場(chǎng)景太多了。讓我們看幾個(gè)事實(shí):
- Node.js 讓我們可以用 Javascript 寫后臺(tái)程序
- Node.js 讓我們寫 Web Browser 前端:一方面,可以通過 Grunt 或者其他持續(xù)集成工具生成可發(fā)布的前端靜態(tài)網(wǎng)站內(nèi)容(例如: Bootstrap); 另一方面,也可以通過 Browserify 在前端代碼中使用 Node.js 的 Modules,讓前后臺(tái)代碼使用統(tǒng)一的代碼基(例如:domready。很多 Node.js 的 Modules 本身就經(jīng)過了瀏覽器兼容測(cè)試,可以同時(shí)運(yùn)行在兩端)。
- 用 Node.js 開發(fā)桌面應(yīng)用,例如:https://github.com/rogerwang/node-webkit/wiki/List-of-apps-and-companies-using-node-webkit,列出了基于 node-webkit 的桌面應(yīng)用列表。
- 即使在性能受限的移動(dòng)設(shè)備中,我們也可以通過 Javascript Binding 將一部分應(yīng)用邏輯用 Javascript 來實(shí)現(xiàn),而 UI 的渲染還是 Native 的方式。這在很多游戲中已經(jīng)被采用(http://www.zhihu.com/question/21130385)。只要用到 Javascript,或者說,隨著 Javascript 代碼基的擴(kuò)大,npm based 的包管理方式就會(huì)通過 Browserify 的方式被慢慢引入。
除了第二個(gè)問題提到的那些不適合 Node.js 的地方,其他領(lǐng)域想徹底不碰 Node.js 是很難的。
Node.js發(fā)展方向
如果你的老板不讓你碰 Node.js,你需要讓他支付青春損失費(fèi)。開個(gè)玩笑:)
投資在 Node.js 不會(huì)吃虧。
基于 Browserify 的貢獻(xiàn),前后臺(tái)一致的代碼基正在成為現(xiàn)實(shí)(在我的一個(gè)項(xiàng)目中已經(jīng)如此,Web Client 通過 Node.js 的 stream 和后端傳遞數(shù)據(jù) )。你可以看到在前端使用原本為后臺(tái)寫的Module,或者用寫后端程序的方法寫前端代碼,例如:domready。瀏覽器中無需運(yùn)行一個(gè)完整的 Node.js,只要打包好需要的 Modules 下載到瀏覽器執(zhí)行即可。
在問題 5 中,大家已經(jīng)看到 Node.js 在分布式計(jì)算領(lǐng)域的應(yīng)用能力。 在問題 8 中,大家可以看到 Node.js 在客戶端開發(fā)中所扮演的角色。
傳統(tǒng)的數(shù)據(jù)庫(kù)這一領(lǐng)域也在發(fā)生變化。通用的數(shù)據(jù)庫(kù)系統(tǒng)在未來會(huì)慢慢“失寵”,“樂高積木”化的存儲(chǔ)服務(wù)會(huì)流行起來。Hackers 們圍繞著 LevelUp構(gòu)建自己的存儲(chǔ)引擎,從 key/value,到Graph DB;從基于 B 樹的一維索引到基于 R-Tree 的多維索引;從能夠在瀏覽器中運(yùn)行的嵌入數(shù)據(jù)庫(kù)到支持成千上萬訪問者,高可用的數(shù)據(jù)庫(kù)系統(tǒng);從支持兩階段提交的 Transaction 到,到支持實(shí)時(shí)增量的 Map-Reduce。在我的一個(gè)項(xiàng)目中已經(jīng)開始采用這種方法,為特定的存儲(chǔ)和查詢需求構(gòu)建特定的存儲(chǔ)服務(wù)。這在以前是不可想象的,但是現(xiàn)在,也就是一個(gè)程序員的工作吧。
我是一個(gè)自己寫程序的“產(chǎn)品經(jīng)理”。每年有8個(gè)月是集中開發(fā)的時(shí)間,剩下的時(shí)間則是負(fù)責(zé)產(chǎn)品設(shè)計(jì)。關(guān)注的方向從 Web、Mobile App. 到后端系統(tǒng)。Node.js 給我提供了無數(shù)塊“樂高積木”,讓我可以拼裝自己的玩具,這是很快樂的體驗(yàn)的過程。遺憾的就是時(shí)間不夠多,有那么多東西沒時(shí)間去了解,去體會(huì)其他人的奇思妙想。小公司也是對(duì)成本極度敏感的,如果沒有 Node.js 很多東西連想都不敢想。