官术网_书友最值得收藏!

1.5 Node的應(yīng)用場景

在進(jìn)行技術(shù)選型之前,需要了解一項(xiàng)新技術(shù)具體適合什么樣的場景,畢竟合適的技術(shù)用在合適的場景可以起到意想不到的效果。關(guān)于Node,探討得較多的主要有I/O密集型和CPU密集型。

1.5.1 I/O密集型

在Node的推廣過程中,無數(shù)次有人問起Node的應(yīng)用場景是什么。如果將所有的腳本語言拿到一處來評判,那么從單線程的角度來說,Node處理I/O的能力是值得豎起拇指稱贊的。通常,說Node擅長I/O密集型的應(yīng)用場景基本上是沒人反對的。Node面向網(wǎng)絡(luò)且擅長并行I/O,能夠有效地組織起更多的硬件資源,從而提供更多好的服務(wù)。

I/O密集的優(yōu)勢主要在于Node利用事件循環(huán)的處理能力,而不是啟動每一個線程為每一個請求服務(wù),資源占用極少。

1.5.2 是否不擅長CPU密集型業(yè)務(wù)

換一個角度,在CPU密集的應(yīng)用場景中,Node是否能勝任呢?實(shí)際上,V8的執(zhí)行效率是十分高的。單以執(zhí)行效率來做評判,V8的執(zhí)行效率是毋庸置疑的。

我們將相同的斐波那契數(shù)列計(jì)算(F0=0, F1=1, Fn=F(n-1)+F(n-2)(n≥2))分別用各種腳本語言寫了算法實(shí)現(xiàn),并進(jìn)行了n = 40的計(jì)算,以比較性能。這個測試主要偏重CPU棧操作,表1-1是其中一次運(yùn)算耗時的排行。在這些腳本語言中(其中C和Go語言是靜態(tài)語言,用于參考), Node是足夠高效的,它優(yōu)秀的運(yùn)算能力主要來自V8的深度性能優(yōu)化。

表1-1 計(jì)算斐波那契數(shù)列的耗時排行

這樣的測試結(jié)果盡管不能完全反映出各個語言的性能優(yōu)劣,但已經(jīng)可以表明Node在性能上不俗的表現(xiàn)。從另一個角度來說,這可以表明CPU密集型應(yīng)用其實(shí)并不可怕。CPU密集型應(yīng)用給Node帶來的挑戰(zhàn)主要是:由于JavaScript單線程的原因,如果有長時間運(yùn)行的計(jì)算(比如大循環(huán)),將會導(dǎo)致CPU時間片不能釋放,使得后續(xù)I/O無法發(fā)起。但是適當(dāng)調(diào)整和分解大型運(yùn)算任務(wù)為多個小任務(wù),使得運(yùn)算能夠適時釋放,不阻塞I/O調(diào)用的發(fā)起,這樣既可同時享受到并行異步I/O的好處,又能充分利用CPU。

關(guān)于CPU密集型應(yīng)用,Node的異步I/O已經(jīng)解決了在單線程上CPU與I/O之間阻塞無法重疊利用的問題,I/O阻塞造成的性能浪費(fèi)遠(yuǎn)比CPU的影響小。對于長時間運(yùn)行的計(jì)算,如果它的耗時超過普通阻塞I/O的耗時,那么應(yīng)用場景就需要重新評估,因?yàn)檫@類計(jì)算比阻塞I/O還影響效率,甚至說就是一個純計(jì)算的場景,根本沒有I/O。此類應(yīng)用場景或許應(yīng)當(dāng)采用多線程的方式進(jìn)行計(jì)算。Node雖然沒有提供多線程用于計(jì)算支持,但是還是有以下兩個方式來充分利用CPU。

? Node可以通過編寫C/C++擴(kuò)展的方式更高效地利用CPU,將一些V8不能做到性能極致的地方通過C/C++來實(shí)現(xiàn)。由上面的測試結(jié)果可以看到,通過C/C++擴(kuò)展的方式實(shí)現(xiàn)斐波那契數(shù)列計(jì)算,速度比Java還快。

? 如果單線程的Node不能滿足需求,甚至用了C/C++擴(kuò)展后還覺得不夠,那么通過子進(jìn)程的方式,將一部分Node進(jìn)程當(dāng)做常駐服務(wù)進(jìn)程用于計(jì)算,然后利用進(jìn)程間的消息來傳遞結(jié)果,將計(jì)算與I/O分離,這樣還能充分利用多CPU。

CPU密集不可怕,如何合理調(diào)度是訣竅。

1.5.3 與遺留系統(tǒng)和平共處

有人會說:“JavaScript一統(tǒng)前后端了,將來會不會干掉其他的語言?”言語中充滿了危機(jī)感。

在Web端,過去大多都是同步的方式編寫的程序,這種串行調(diào)用下層應(yīng)用數(shù)據(jù)的過程中充斥著串行的等待時間,如果采用多線程來解決這種串行等待,又或多或少地顯得小題大作。在Node中,語言層面即可天然并行的特性在這種場景中顯得十分有效。對于已有的穩(wěn)定系統(tǒng),并非意味著我們要拋棄掉。

LinkedIn在他們的移動版網(wǎng)站上的實(shí)踐非常典型地說明了這個問題。舊有的系統(tǒng)具有非常穩(wěn)定的數(shù)據(jù)輸出,持續(xù)為傳統(tǒng)網(wǎng)站服務(wù),同時為移動版提供數(shù)據(jù)源,Node將該數(shù)據(jù)源當(dāng)做數(shù)據(jù)接口,發(fā)揮異步并行的優(yōu)勢,而不用關(guān)心它背后是用什么語言實(shí)現(xiàn)的。

這方面,國內(nèi)的雪球財(cái)經(jīng)也有很好的實(shí)踐。雪球財(cái)經(jīng)是從舊有的Java項(xiàng)目中分離出一個子項(xiàng)目,在這個子項(xiàng)目中,沒有繼續(xù)采用Java/JSP而是采用Node來完成Web端的開發(fā),使得前端工程師在HTTP協(xié)議棧的兩端能夠高效靈活地開發(fā),避免了Java煩瑣的表達(dá);另一方面,又利用Java作為后端接口和中間件,使其具有良好的穩(wěn)定性。兩者互相結(jié)合,取長補(bǔ)短。

1.5.4 分布式應(yīng)用

阿里巴巴的數(shù)據(jù)平臺對Node的分布式應(yīng)用算是一個典型的例子。分布式應(yīng)用意味著對可伸縮性的要求非常高。數(shù)據(jù)平臺通常要在一個數(shù)據(jù)庫集群中去尋找需要的數(shù)據(jù)。阿里巴巴開發(fā)了中間層應(yīng)用NodeFox、ITier,將數(shù)據(jù)庫集群做了劃分和映射,查詢調(diào)用依舊是針對單張表進(jìn)行SQL查詢,中間層分解查詢SQL,并行地去多臺數(shù)據(jù)庫中獲取數(shù)據(jù)并合并。NodeFox能實(shí)現(xiàn)對多臺MySQL數(shù)據(jù)庫的查詢,如同查詢一臺MySQL一樣,而ITier更強(qiáng)大,查詢多個數(shù)據(jù)庫如同查詢單個數(shù)據(jù)庫一樣,這里的多個數(shù)據(jù)庫是指不同的數(shù)據(jù)庫,如MySQL或其他的數(shù)據(jù)庫。

這個案例其實(shí)也是高效利用并行I/O的例子。Node高效利用并行I/O的過程,也是高效使用數(shù)據(jù)庫的過程。對于Node,這個行為只是一次普通的I/O。對于數(shù)據(jù)庫而言,卻是一次復(fù)雜的計(jì)算,所以也是進(jìn)而充分壓榨硬件資源的過程。

主站蜘蛛池模板: 洛扎县| 哈尔滨市| 保定市| 扬州市| 台中市| 孝昌县| 广东省| 大新县| 龙川县| 清远市| 阳西县| 泰和县| 鹿邑县| 博兴县| 上虞市| 扬州市| 桓仁| 靖边县| 大荔县| 聊城市| 葵青区| 济源市| 墨玉县| 溧阳市| 依安县| 会宁县| 临桂县| 离岛区| 鄂托克旗| 宁强县| 望都县| 邹城市| 同心县| 南溪县| 洛浦县| 油尖旺区| 巫山县| 锡林郭勒盟| 综艺| 济南市| 宁强县|