服務(wù)端I/O性能大比拼:Node烤黍、PHP、Java傻盟、Go

原文:Server-side I/O Performance: Node vs. PHP vs. Java vs. Go

作者:BRAD PEABODY 翻譯:雁驚寒

摘要:本文首先簡單介紹了I/O相關(guān)的基礎(chǔ)概念速蕊,然后橫向比較了Node、PHP娘赴、Java规哲、Go的I/O性能,并給出了選型建議诽表。以下是譯文唉锌。

了解應(yīng)用程序的輸入/輸出(I/O)模型能夠更好的理解它在處理負(fù)載時(shí)理想情況與實(shí)際情況下的差異。也許你的應(yīng)用程序很小竿奏,也無需支撐太高的負(fù)載袄简,所以這方面需要考慮的東西還比較少。但是泛啸,隨著應(yīng)用程序流量負(fù)載的增加绿语,使用錯(cuò)誤的I/O模型可能會(huì)導(dǎo)致非常嚴(yán)重的后果。

在本文中候址,我們將把Node吕粹、Java、Go和PHP與Apache配套進(jìn)行比較岗仑,討論不同語言如何對(duì)I/O進(jìn)行建模匹耕、每個(gè)模型的優(yōu)缺點(diǎn),以及一些基本的性能評(píng)測(cè)赔蒲。如果你比較關(guān)心自己下一個(gè)Web應(yīng)用程序的I/O性能泌神,本文將為你提供幫助良漱。

I/O基礎(chǔ):快速回顧一下

要了解與I/O相關(guān)的因素,我們必須首先在操作系統(tǒng)層面上了解這些概念欢际。雖然不太可能一上來就直接接觸到太多的概念母市,但在應(yīng)用的運(yùn)行過程中,不管是直接還是間接损趋,總會(huì)遇到它們患久。細(xì)節(jié)很重要。

系統(tǒng)調(diào)用

首先浑槽,我們來認(rèn)識(shí)下系統(tǒng)調(diào)用蒋失,具體描述如下:

應(yīng)用程序請(qǐng)求操作系統(tǒng)內(nèi)核為其執(zhí)行I/O操作。

“系統(tǒng)調(diào)用”是指程序請(qǐng)求內(nèi)核執(zhí)行某些操作桐玻。其實(shí)現(xiàn)細(xì)節(jié)因操作系統(tǒng)而異篙挽,但基本概念是相同的。在執(zhí)行“系統(tǒng)調(diào)用”時(shí)镊靴,將會(huì)有一些控制程序的特定指令轉(zhuǎn)移到內(nèi)核中去铣卡。一般來說,系統(tǒng)調(diào)用是阻塞的偏竟,這意味著程序會(huì)一直等待直到內(nèi)核返回結(jié)果煮落。

內(nèi)核在物理設(shè)備(磁盤、網(wǎng)卡等)上執(zhí)行底層I/O操作并回復(fù)系統(tǒng)調(diào)用踊谋。在現(xiàn)實(shí)世界中蝉仇,內(nèi)核可能需要做很多事情來滿足你的請(qǐng)求,包括等待設(shè)備準(zhǔn)備就緒殖蚕、更新其內(nèi)部狀態(tài)等等轿衔,但作為一名應(yīng)用程序開發(fā)人員,你無需關(guān)心這些嫌褪,這是內(nèi)核的事情呀枢。

阻塞調(diào)用與非阻塞調(diào)用

我在上面說過胚股,系統(tǒng)調(diào)用一般來說是阻塞的笼痛。但是,有些調(diào)用卻屬于“非阻塞”的琅拌,這意味著內(nèi)核會(huì)將請(qǐng)求放入隊(duì)列或緩沖區(qū)中缨伊,然后立即返回而不等待實(shí)際I/O的發(fā)生。所以进宝,它只會(huì)“阻塞”很短的時(shí)間刻坊,但排隊(duì)需要一定的時(shí)間。

為了說明這一點(diǎn)党晋,下面給出幾個(gè)例子(Linux系統(tǒng)調(diào)用):

read()是一個(gè)阻塞調(diào)用谭胚。我們需要傳遞一個(gè)文件句柄和用于保存數(shù)據(jù)的緩沖區(qū)給它徐块,當(dāng)數(shù)據(jù)保存到緩沖區(qū)之后返回。它的優(yōu)點(diǎn)是優(yōu)雅而又簡單灾而。

epoll_create()胡控、epoll_ctl()和epoll_wait()可用于創(chuàng)建一組句柄進(jìn)行監(jiān)聽,添加/刪除這個(gè)組中的句柄旁趟、阻塞程序直到句柄有任何的活動(dòng)昼激。這些系統(tǒng)調(diào)用能讓你只用單個(gè)線程就能高效地控制大量的I/O操作。這些功能雖然非常有用锡搜,但使用起來相當(dāng)復(fù)雜橙困。

了解這里的時(shí)間差的數(shù)量級(jí)非常重要。如果一個(gè)沒有優(yōu)化過的CPU內(nèi)核以3GHz的頻率運(yùn)行耕餐,那么它可以每秒執(zhí)行30億個(gè)周期(即每納秒3個(gè)周期)凡傅。一個(gè)非阻塞的系統(tǒng)調(diào)用可能需要大約10多個(gè)周期,或者說幾個(gè)納秒肠缔。對(duì)從網(wǎng)絡(luò)接收信息的調(diào)用進(jìn)行阻塞可能需要更長的時(shí)間像捶,比如說200毫秒(1/5秒)。比方說桩砰,非阻塞調(diào)用花了20納秒拓春,阻塞調(diào)用花了200,000,000納秒。這樣亚隅,進(jìn)程為了阻塞調(diào)用可能就要等待1000萬個(gè)周期硼莽。

內(nèi)核提供了阻塞I/O(“從網(wǎng)絡(luò)讀取數(shù)據(jù)”)和非阻塞I/O(“告訴我網(wǎng)絡(luò)連接上什么時(shí)候有新數(shù)據(jù)”)這兩種方法,并且兩種機(jī)制阻塞調(diào)用進(jìn)程的時(shí)間長短完全不同煮纵。

調(diào)度

第三個(gè)非常關(guān)鍵的事情是當(dāng)有很多線程或進(jìn)程開始出現(xiàn)阻塞時(shí)會(huì)發(fā)生什么問題懂鸵。

對(duì)我們而言,線程和進(jìn)程之間并沒有太大的區(qū)別行疏。而在現(xiàn)實(shí)中匆光,與性能相關(guān)的最顯著的區(qū)別是,由于線程共享相同的內(nèi)存酿联,并且每個(gè)進(jìn)程都有自己的內(nèi)存空間终息,所以單個(gè)進(jìn)程往往會(huì)占用更多的內(nèi)存。但是贞让,在我們談?wù)撜{(diào)度的時(shí)候周崭,實(shí)際上講的是完成一系列的事情,并且每個(gè)事情都需要在可用的CPU內(nèi)核上獲得一定的執(zhí)行時(shí)間喳张。如果你有8個(gè)內(nèi)核來運(yùn)行300個(gè)線程续镇,那么你必須把時(shí)間分片,這樣销部,每個(gè)線程才能獲得屬于它的時(shí)間片摸航,每一個(gè)內(nèi)核運(yùn)行很短的時(shí)間制跟,然后切換到下一個(gè)線程。這是通過“上下文切換”完成的酱虎,可以讓CPU從一個(gè)線程/進(jìn)程切換到下一個(gè)線程/進(jìn)程凫岖。

這種上下文切換有一定的成本,即需要一定的時(shí)間逢净「绶牛快的時(shí)候可能會(huì)小于100納秒,但如果實(shí)現(xiàn)細(xì)節(jié)爹土、處理器速度/架構(gòu)甥雕、CPU緩存等軟硬件的不同,花個(gè)1000納秒或更長的時(shí)間也很正常胀茵。

線程(或進(jìn)程)數(shù)量越多社露,則上下文切換的次數(shù)也越多。如果存在成千上萬的線程琼娘,每個(gè)線程都要耗費(fèi)幾百納秒的切換時(shí)間的時(shí)候峭弟,系統(tǒng)就會(huì)變得非常慢。

然而脱拼,非阻塞調(diào)用實(shí)質(zhì)上告訴內(nèi)核“只有在這些連接上有新的數(shù)據(jù)或事件到來時(shí)才調(diào)用我”瞒瘸。這些非阻塞調(diào)用可有效地處理大I/O負(fù)載并減少上下文切換。

值得注意的是熄浓,雖然本文舉得例子很小情臭,但數(shù)據(jù)庫訪問、外部緩存系統(tǒng)(memcache之類的)以及任何需要I/O的東西最終都會(huì)執(zhí)行某種類型的I/O調(diào)用赌蔑,這跟示例的原理是一樣的俯在。

影響項(xiàng)目中編程語言選擇的因素有很多,即使你只考慮性能方面娃惯,也存在很多的因素跷乐。但是,如果你擔(dān)心自己的程序主要受I/O的限制趾浅,并且性能是決定項(xiàng)目成功或者失敗的重要因素愕提,那么,下文提到的幾點(diǎn)建議就是你需要重點(diǎn)考慮的潮孽。

“保持簡單”:PHP

早在上世紀(jì)90年代揪荣,有很多人穿著Converse鞋子使用Perl編寫CGI腳本。然后往史,PHP來了,很多人都喜歡它佛舱,它使得動(dòng)態(tài)網(wǎng)頁的制作更加容易椎例。

PHP使用的模型非常簡單挨决。雖然不可能完全相同,但一般的PHP服務(wù)器原理是這樣的:

用戶瀏覽器發(fā)出一個(gè)HTTP請(qǐng)求订歪,請(qǐng)求進(jìn)入到Apache web服務(wù)器中脖祈。 Apache為每個(gè)請(qǐng)求創(chuàng)建一個(gè)單獨(dú)的進(jìn)程,并通過一些優(yōu)化手段對(duì)這些進(jìn)程進(jìn)行重用刷晋,從而最大限度地減少原本需要執(zhí)行的操作(創(chuàng)建進(jìn)程相對(duì)而言是比較慢的)盖高。

Apache調(diào)用PHP并告訴它運(yùn)行磁盤上的某個(gè).php文件。

PHP代碼開始執(zhí)行眼虱,并阻塞I/O調(diào)用喻奥。你在PHP中調(diào)用的file_get_contents(),在底層實(shí)際上是調(diào)用了read()系統(tǒng)調(diào)用并等待返回的結(jié)果捏悬。


與系統(tǒng)的集成示意圖是這樣的:

很簡單:每個(gè)請(qǐng)求一個(gè)進(jìn)程撞蚕。

I/O調(diào)用是阻塞的。那么優(yōu)點(diǎn)呢过牙?簡單而又有效甥厦。缺點(diǎn)呢?如果有20000個(gè)客戶端并發(fā)寇钉,服務(wù)器將會(huì)癱瘓刀疙。這種方法擴(kuò)展起來比較難,因?yàn)閮?nèi)核提供的用于處理大量I/O(epoll等)的工具并沒有充分利用起來扫倡。更糟糕的是庙洼,為每個(gè)請(qǐng)求運(yùn)行一個(gè)單獨(dú)的進(jìn)程往往會(huì)占用大量的系統(tǒng)資源,尤其是內(nèi)存镊辕,這通常是第一個(gè)耗盡的油够。

*注意:在這一點(diǎn)上,Ruby的情況與PHP非常相似征懈。

多線程:Java

所以石咬,Java就出現(xiàn)了。而且Java在語言中內(nèi)置了多線程卖哎,特別是在創(chuàng)建線程時(shí)非常得棒鬼悠。

大多數(shù)的Java Web服務(wù)器都會(huì)為每個(gè)請(qǐng)求啟動(dòng)一個(gè)新的執(zhí)行線程,然后在這個(gè)線程中調(diào)用開發(fā)人員編寫的函數(shù)亏娜。

在Java Servlet中執(zhí)行I/O往往是這樣的:


由于上面的doGet方法對(duì)應(yīng)于一個(gè)請(qǐng)求焕窝,并且在自己的線程中運(yùn)行,而不是在需要有獨(dú)立內(nèi)存的單獨(dú)進(jìn)程中運(yùn)行维贺,所以我們將創(chuàng)建一個(gè)單獨(dú)的線程它掂。每個(gè)請(qǐng)求都會(huì)得到一個(gè)新的線程,并在該線程內(nèi)部阻塞各種I/O操作,直到請(qǐng)求處理完成虐秋。應(yīng)用會(huì)創(chuàng)建一個(gè)線程池以最小化創(chuàng)建和銷毀線程的成本榕茧,但是,成千上萬的連接意味著有成千上萬的線程客给,這對(duì)于調(diào)度器來說并不件好事情用押。

值得注意的是,1.4版本的Java(1.7版本中又重新做了升級(jí))增加了非阻塞I/O調(diào)用的能力靶剑。雖然大多數(shù)的應(yīng)用程序都沒有使用這個(gè)特性蜻拨,但它至少是可用的。一些Java

Web服務(wù)器正在嘗試使用這個(gè)特性桩引,但絕大部分已經(jīng)部署的Java應(yīng)用程序仍然按照上面所述的原理進(jìn)行工作缎讼。

Java提供了很多在I/O方面開箱即用的功能,但如果遇到創(chuàng)建大量阻塞線程執(zhí)行大量I/O操作的情況時(shí)阐污,Java也沒有太好的解決方案休涤。

把非阻塞I/O作為頭等大事:Node

在I/O方面表現(xiàn)比較好的、比較受用戶歡迎的是Node.js笛辟。任何一個(gè)對(duì)Node有簡單了解的人都知道功氨,它是“非阻塞”的,并且能夠高效地處理I/O手幢。這在一般意義上是正確的捷凄。但是細(xì)節(jié)和實(shí)現(xiàn)的方式至關(guān)重要。

在需要做一些涉及I/O的操作的時(shí)候围来,你需要發(fā)出請(qǐng)求跺涤,并給出一個(gè)回調(diào)函數(shù),Node會(huì)在處理完請(qǐng)求之后調(diào)用這個(gè)函數(shù)监透。

在請(qǐng)求中執(zhí)行I/O操作的典型代碼如下所示:


如上所示桶错,這里有兩個(gè)回調(diào)函數(shù)。當(dāng)請(qǐng)求開始時(shí)胀蛮,第一個(gè)函數(shù)會(huì)被調(diào)用院刁,而第二個(gè)函數(shù)是在文件數(shù)據(jù)可用時(shí)被調(diào)用。

這樣粪狼,Node就能更有效地處理這些回調(diào)函數(shù)的I/O退腥。有一個(gè)更能說明問題的例子:在Node中調(diào)用數(shù)據(jù)庫操作。首先再榄,你的程序開始調(diào)用數(shù)據(jù)庫操作狡刘,并給Node一個(gè)回調(diào)函數(shù),Node會(huì)使用非阻塞調(diào)用來單獨(dú)執(zhí)行I/O操作困鸥,然后在請(qǐng)求的數(shù)據(jù)可用時(shí)調(diào)用你的回調(diào)函數(shù)嗅蔬。這種對(duì)I/O調(diào)用進(jìn)行排隊(duì)并讓Node處理I/O調(diào)用然后得到一個(gè)回調(diào)的機(jī)制稱為“事件循環(huán)”。這個(gè)機(jī)制非常不錯(cuò)。

然而购城,這個(gè)模型有一個(gè)問題吕座。在底層虐译,這個(gè)問題出現(xiàn)的原因跟V8

JavaScript引擎(Node使用的是Chrome的JS引擎)的實(shí)現(xiàn)有關(guān)瘪板,即:你寫的JS代碼都運(yùn)行在一個(gè)線程中。請(qǐng)思考一下漆诽。這意味著侮攀,盡管使用高效的非阻塞技術(shù)來執(zhí)行I/O,但是JS代碼在單個(gè)線程操作中運(yùn)行基于CPU的操作厢拭,每個(gè)代碼塊都會(huì)阻塞下一個(gè)代碼塊的運(yùn)行兰英。有一個(gè)常見的例子:在數(shù)據(jù)庫記錄上循環(huán)供鸠,以某種方式處理記錄,然后將它們輸出到客戶端薄坏。下面這段代碼展示了這個(gè)例子的原理:


雖然Node處理I/O的效率很高寨闹,但是上面例子中的for循環(huán)在一個(gè)主線程中使用了CPU周期。這意味著如果你有10000個(gè)連接繁堡,那么這個(gè)循環(huán)就可能會(huì)占用整個(gè)應(yīng)用程序的時(shí)間。每個(gè)請(qǐng)求都必須要在主線程中占用一小段時(shí)間椭蹄。

這整個(gè)概念的前提是I/O操作是最慢的部分闻牡,因此,即使串行處理是不得已的罩润,但對(duì)它們進(jìn)行有效處理也是非常重要的哨啃。這在某些情況下是成立的写妥,但并非一成不變。

另一點(diǎn)觀點(diǎn)是祝峻,寫一堆嵌套的回調(diào)很麻煩莱找,有些人認(rèn)為這樣的代碼很丑陋。在Node代碼中嵌入四個(gè)辞色、五個(gè)甚至更多層的回調(diào)并不罕見相满。

又到了權(quán)衡利弊的時(shí)候了立美。如果你的主要性能問題是I/O的話方灾,那么這個(gè)Node模型能幫到你。但是洞慎,它的缺點(diǎn)在于拢蛋,如果你在一個(gè)處理HTTP請(qǐng)求的函數(shù)中放入了CPU處理密集型代碼的話蔫巩,一不小心就會(huì)讓每個(gè)連接都出現(xiàn)擁堵圆仔。

原生無阻塞:Go

在介紹Go之前坪郭,我透露一下,我是一個(gè)Go的粉絲嗦锐。我已經(jīng)在許多項(xiàng)目中使用了Go奕污。

讓我們看看它是如何處理I/O的吧液走。

Go語言的一個(gè)關(guān)鍵特性是它包含了自己的調(diào)度器。它并不會(huì)為每個(gè)執(zhí)行線程對(duì)應(yīng)一個(gè)操作系統(tǒng)線程嘱根,而是使用了“goroutines”這個(gè)概念该抒。Go運(yùn)行時(shí)會(huì)為一個(gè)goroutine分配一個(gè)操作系統(tǒng)線程,并控制它執(zhí)行或暫停蒋譬。Go

HTTP服務(wù)器的每個(gè)請(qǐng)求都在一個(gè)單獨(dú)的Goroutine中進(jìn)行處理。

調(diào)度程序的工作原理如下所示:

實(shí)際上维咸,除了回調(diào)機(jī)制被內(nèi)置到I/O調(diào)用的實(shí)現(xiàn)中并自動(dòng)與調(diào)度器交互之外惠爽,Go運(yùn)行時(shí)正在做的事情與Node不同婚肆。它也不會(huì)受到必須讓所有的處理代碼在同一個(gè)線程中運(yùn)行的限制,Go會(huì)根據(jù)其調(diào)度程序中的邏輯自動(dòng)將你的Goroutine映射到它認(rèn)為合適的操作系統(tǒng)線程中用僧。因此责循,它的代碼是這樣的:

如上所示院仿,這樣的基本代碼結(jié)構(gòu)更為簡單,而且還實(shí)現(xiàn)了非阻塞I/O歹垫。

在大多數(shù)情況下排惨,這真正做到了“兩全其美”若贮。非阻塞I/O可用于所有重要的事情,但是代碼卻看起來像是阻塞的蠢沿,因此這樣往往更容易理解和維護(hù)匾效。

剩下的就是Go調(diào)度程序和OS調(diào)度程序之間的交互處理了面哼。這并不是魔法魔策,如果你正在建立一個(gè)大型系統(tǒng),那么還是值得花時(shí)間去了解它的工作原理的虎敦。同時(shí)其徙,“開箱即用”的特點(diǎn)使它能夠更好地工作和擴(kuò)展唾那。

Go可能也有不少缺點(diǎn)闹获,但總的來說昌罩,它處理I/O的方式并沒有明顯的缺點(diǎn)茎用。

性能評(píng)測(cè)

對(duì)于這些不同模型的上下文切換睬罗,很難進(jìn)行準(zhǔn)確的計(jì)時(shí)容达。當(dāng)然,我也可以說這對(duì)你并沒有多大的用處羡滑。這里柒昏,我將對(duì)這些服務(wù)器環(huán)境下的HTTP服務(wù)進(jìn)行基本的性能評(píng)測(cè)比較。請(qǐng)記住职祷,端到端的HTTP請(qǐng)求/響應(yīng)性能涉及到的因素有很多。

我針對(duì)每一個(gè)環(huán)境都寫了一段代碼來讀取64k文件中的隨機(jī)字節(jié)是尖,然后對(duì)其運(yùn)行N次SHA-256散列(在URL的查詢字符串中指定N饺汹,例如.../test.php?n=100)并以十六進(jìn)制打印結(jié)果首繁。我之所以選擇這個(gè),是因?yàn)樗梢院苋菀走\(yùn)行一些持續(xù)的I/O操作夹攒,并且可以通過受控的方式來增加CPU使用率压语。

首先胎食,我們來看一些低并發(fā)性的例子允懂。使用300個(gè)并發(fā)請(qǐng)求運(yùn)行2000次迭代厕怜,每個(gè)請(qǐng)求哈希一次(N=1),結(jié)果如下:

Times是完成所有并發(fā)請(qǐng)求的平均毫秒數(shù)蕾总。越低越好粥航。

從單單這一張圖中很難得到結(jié)論,但我個(gè)人認(rèn)為生百,在這種存在大量連接和計(jì)算的情況下递雀,我們看到的結(jié)果更多的是與語言本身的執(zhí)行有關(guān)。請(qǐng)注意蚀浆,“腳本語言”的執(zhí)行速度最慢擎析。

但是如果我們將N增加到1000,但仍然是300個(gè)并發(fā)請(qǐng)求募壕,即在相同的負(fù)載的情況下將散列的迭代次數(shù)增加了1000倍(CPU負(fù)載明顯更高)僵刮,會(huì)發(fā)生什么情況呢:

Times是完成所有并發(fā)請(qǐng)求的平均毫秒數(shù)曼追。越低越好。

突然之間碟狞,由于每個(gè)請(qǐng)求中的CPU密集型操作相互阻塞,Node的性能顯著下降。有趣的是盖溺,在這個(gè)測(cè)試中攘残,PHP的性能變得更好了(相對(duì)于其他),甚至優(yōu)于Java牍蜂。

(值得注意的是,在PHP中寄疏,SHA-256的實(shí)現(xiàn)是用C語言編寫的批什,但執(zhí)行路徑在這個(gè)循環(huán)中花費(fèi)了更多的時(shí)間,因?yàn)槲覀冞@次做了1000次哈希迭代)暮的。

現(xiàn)在翩伪,讓我們?cè)囋?000個(gè)并發(fā)連接(N=1) 。不幸的是,對(duì)于大多數(shù)的環(huán)境來說,失敗率并不明顯豹休。我們來看看這個(gè)圖表中每秒處理的請(qǐng)求數(shù),越高越好

每秒處理的請(qǐng)求數(shù),越高越好。

這個(gè)圖看起來跟上面的不太一樣。我猜測(cè),在較高的連接數(shù)量下,PHP + Apache中產(chǎn)生新進(jìn)程和內(nèi)存的申請(qǐng)似乎成為了影響PHP性能的主要因素。很顯然凄吏,Go是這次的贏家序六,其次是Java随抠,Node扔罪,最后是PHP背犯。

雖然涉及到整體吞吐量的因素很多妄均,而且應(yīng)用程序和應(yīng)用程序之間也存在著很大的差異,但是邑彪,越是了解底層的原理和所涉及的權(quán)衡問題寄症,應(yīng)用程序的表現(xiàn)就會(huì)越好宙彪。

總結(jié)

綜上所述,隨著語言的發(fā)展有巧,處理大量I/O大型應(yīng)用程序的解決方案也隨之發(fā)展释漆。

公平地說男图,PHP和Java在web應(yīng)用方面都有可用非阻塞I/O實(shí)現(xiàn)览露。但是這些實(shí)現(xiàn)并不像上面描述的方法那么使用廣泛,并且還需要考慮維護(hù)上的開銷苟翻。更不用說應(yīng)用程序的代碼必須以適合這種環(huán)境的方式來構(gòu)建父款。

我們來比較一下幾個(gè)影響性能和易用性的重要因素:

語言線程與進(jìn)程非阻塞I/O易于使用

PHP進(jìn)程否-

Java線程有效需要回調(diào)

Node.js線程是需要回調(diào)

Go線程 (Goroutines)是無需回調(diào)

因?yàn)榫€程會(huì)共享相同的內(nèi)存空間憨攒,而進(jìn)程不會(huì),所以線程通常要比進(jìn)程的內(nèi)存效率高得多鲫构。在上面的列表中浓恶,從上往下看,與I/O相關(guān)的因素一個(gè)比一個(gè)好结笨。所以包晰,如果我不得不在上面的比較中選擇一個(gè)贏家,那肯定選Go炕吸。

即便如此伐憾,在實(shí)踐中,選擇構(gòu)建應(yīng)用程序的環(huán)境與你團(tuán)隊(duì)對(duì)環(huán)境的熟悉程度以及團(tuán)隊(duì)可以實(shí)現(xiàn)的整體生產(chǎn)力密切相關(guān)赫模。所以树肃,對(duì)于團(tuán)隊(duì)來說,使用Node或Go來開發(fā)Web應(yīng)用程序和服務(wù)可能并不是最好的選擇瀑罗。

希望以上這些內(nèi)容能夠幫助你更清楚地了解底層發(fā)生的事情胸嘴,并為你提供一些關(guān)于如何處理應(yīng)用程序伸縮性的建議。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斩祭,一起剝皮案震驚了整個(gè)濱河市劣像,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摧玫,老刑警劉巖耳奕,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡屋群,警方通過查閱死者的電腦和手機(jī)闸婴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芍躏,“玉大人邪乍,你說我怎么就攤上這事≈饺猓” “怎么了溺欧?”我有些...
    開封第一講書人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柏肪。 經(jīng)常有香客問我姐刁,道長,這世上最難降的妖魔是什么烦味? 我笑而不...
    開封第一講書人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任聂使,我火速辦了婚禮,結(jié)果婚禮上谬俄,老公的妹妹穿的比我還像新娘柏靶。我一直安慰自己,他們只是感情好溃论,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開白布屎蜓。 她就那樣靜靜地躺著,像睡著了一般钥勋。 火紅的嫁衣襯著肌膚如雪炬转。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,850評(píng)論 1 290
  • 那天算灸,我揣著相機(jī)與錄音扼劈,去河邊找鬼。 笑死菲驴,一個(gè)胖子當(dāng)著我的面吹牛荐吵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赊瞬,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼先煎,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了巧涧?” 一聲冷哼從身側(cè)響起榨婆,我...
    開封第一講書人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎褒侧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闷供,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年烟央,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歪脏。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疑俭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婿失,到底是詐尸還是另有隱情钞艇,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布豪硅,位于F島的核電站哩照,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏懒浮。R本人自食惡果不足惜飘弧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砚著。 院中可真熱鬧次伶,春花似錦、人聲如沸稽穆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舌镶。三九已至柱彻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乎折,已是汗流浹背绒疗。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骂澄,地道東北人吓蘑。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像坟冲,于是被迫代替她去往敵國和親磨镶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349