自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

服務(wù)端I/O性能:Node、PHP、Java、Go的對比

開發(fā)
在本文中,我們將對 Node、Java、Go 和 PHP + Apache 進行對比,討論不同語言如何構(gòu)造其 I/O ,每個模型的優(yōu)缺點,并總結(jié)一些基本的規(guī)律。如果你擔(dān)心你的下一個 Web 應(yīng)用程序的 I/O 性能,本文將給你最優(yōu)的解答。

[[208153]]

了解應(yīng)用程序的輸入/輸出(I/O)模型意味著理解應(yīng)用程序處理其數(shù)據(jù)的載入差異,并揭示其在真實環(huán)境中表現(xiàn)?;蛟S你的應(yīng)用程序很小,在不承受很大的負(fù)載時,這并不是個嚴(yán)重的問題;但隨著應(yīng)用程序的流量負(fù)載增加,可能因為使用了低效的 I/O 模型導(dǎo)致承受不了而崩潰。

和大多數(shù)情況一樣,處理這種問題的方法有多種方式,這不僅僅是一個擇優(yōu)的問題,而是對權(quán)衡的理解問題。 接下來我們來看看 I/O 到底是什么。

在本文中,我們將對 Node、Java、Go 和 PHP + Apache 進行對比,討論不同語言如何構(gòu)造其 I/O ,每個模型的優(yōu)缺點,并總結(jié)一些基本的規(guī)律。如果你擔(dān)心你的下一個 Web 應(yīng)用程序的 I/O 性能,本文將給你***的解答。

I/O 基礎(chǔ)知識: 快速復(fù)習(xí)

要了解 I/O 所涉及的因素,我們首先深入到操作系統(tǒng)層面復(fù)習(xí)這些概念。雖然看起來并不與這些概念直接打交道,但你會一直通過應(yīng)用程序的運行時環(huán)境與它們間接接觸。了解細(xì)節(jié)很重要。

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

首先是系統(tǒng)調(diào)用,其被描述如下:

  • 程序(所謂“用戶端user land”)必須請求操作系統(tǒng)內(nèi)核代表它執(zhí)行 I/O 操作。
  • “系統(tǒng)調(diào)用syscall”是你的程序要求內(nèi)核執(zhí)行某些操作的方法。這些實現(xiàn)的細(xì)節(jié)在操作系統(tǒng)之間有所不同,但基本概念是相同的。有一些具體的指令會將控制權(quán)從你的程序轉(zhuǎn)移到內(nèi)核(類似函數(shù)調(diào)用,但是使用專門用于處理這種情況的專用方式)。一般來說,系統(tǒng)調(diào)用會被阻塞,這意味著你的程序會等待內(nèi)核返回(控制權(quán)到)你的代碼。
  • 內(nèi)核在所需的物理設(shè)備( 磁盤、網(wǎng)卡等 )上執(zhí)行底層 I/O 操作,并回應(yīng)系統(tǒng)調(diào)用。在實際情況中,內(nèi)核可能需要做許多事情來滿足你的要求,包括等待設(shè)備準(zhǔn)備就緒、更新其內(nèi)部狀態(tài)等,但作為應(yīng)用程序開發(fā)人員,你不需要關(guān)心這些。這是內(nèi)核的工作。

 

Syscalls Diagram

阻塞與非阻塞

上面我們提到過,系統(tǒng)調(diào)用是阻塞的,一般來說是這樣的。然而,一些調(diào)用被歸類為“非阻塞”,這意味著內(nèi)核會接收你的請求,將其放在隊列或緩沖區(qū)之類的地方,然后立即返回而不等待實際的 I/O 發(fā)生。所以它只是在很短的時間內(nèi)“阻塞”,只需要排隊你的請求即可。

舉一些 Linux 系統(tǒng)調(diào)用的例子可能有助于理解:

  • read() 是一個阻塞調(diào)用 - 你傳遞一個句柄,指出哪個文件和緩沖區(qū)在哪里傳送它所讀取的數(shù)據(jù),當(dāng)數(shù)據(jù)就緒時,該調(diào)用返回。這種方式的優(yōu)點是簡單友好。
  • 分別調(diào)用 epoll_create()、epoll_ctl() 和 epoll_wait() ,你可以創(chuàng)建一組句柄來偵聽、添加/刪除該組中的處理程序、然后阻塞直到有任何事件發(fā)生。這允許你通過單個線程有效地控制大量的 I/O 操作,但是現(xiàn)在談這個還太早。如果你需要這個功能當(dāng)然好,但須知道它使用起來是比較復(fù)雜的。

了解這里的時間差異的數(shù)量級是很重要的。假設(shè) CPU 內(nèi)核運行在 3GHz,在沒有進行 CPU 優(yōu)化的情況下,那么它每秒執(zhí)行 30 億次周期cycle(即每納秒 3 個周期)。非阻塞系統(tǒng)調(diào)用可能需要幾十個周期來完成,或者說 “相對少的納秒” 時間完成。而一個被跨網(wǎng)絡(luò)接收信息所阻塞的系統(tǒng)調(diào)用可能需要更長的時間 - 例如 200 毫秒(1/5 秒)。這就是說,如果非阻塞調(diào)用需要 20 納秒,阻塞調(diào)用需要 2 億納秒。你的進程因阻塞調(diào)用而等待了 1000 萬倍的時長!

 

Blocking vs. Non-blocking Syscalls

內(nèi)核既提供了阻塞 I/O (“從網(wǎng)絡(luò)連接讀取并給出數(shù)據(jù)”),也提供了非阻塞 I/O (“告知我何時這些網(wǎng)絡(luò)連接具有新數(shù)據(jù)”)的方法。使用的是哪種機制對調(diào)用進程的阻塞時長有截然不同的影響。

調(diào)度

關(guān)鍵的第三件事是當(dāng)你有很多線程或進程開始阻塞時會發(fā)生什么。

根據(jù)我們的理解,線程和進程之間沒有很大的區(qū)別。在現(xiàn)實生活中,最顯著的性能相關(guān)的差異在于,由于線程共享相同的內(nèi)存,而進程每個都有自己的內(nèi)存空間,使得單獨的進程往往占用更多的內(nèi)存。但是當(dāng)我們談?wù)撜{(diào)度Scheduling時,它真正歸結(jié)為一類事情(線程和進程類同),每個都需要在可用的 CPU 內(nèi)核上獲得一段執(zhí)行時間。如果你有 300 個線程運行在 8 個內(nèi)核上,則必須將時間分成幾份,以便每個線程和進程都能分享它,每個運行一段時間,然后交給下一個。這是通過 “上下文切換context switch” 完成的,可以使 CPU 從運行到一個線程/進程到切換下一個。

這些上下文切換也有相關(guān)的成本 - 它們需要一些時間。在某些快速的情況下,它可能小于 100 納秒,但根據(jù)實際情況、處理器速度/體系結(jié)構(gòu)、CPU 緩存等,偶見花費 1000 納秒或更長時間。

而線程(或進程)越多,上下文切換就越多。當(dāng)我們涉及數(shù)以千計的線程時,每個線程花費數(shù)百納秒,就會變得很慢。

然而,非阻塞調(diào)用實質(zhì)上是告訴內(nèi)核“僅在這些連接之一有新的數(shù)據(jù)或事件時再叫我”。這些非阻塞調(diào)用旨在有效地處理大量 I/O 負(fù)載并減少上下文交換。

這些你明白了么?現(xiàn)在來到了真正有趣的部分:我們來看看一些流行的語言對那些工具的使用,并得出關(guān)于易用性和性能之間權(quán)衡的結(jié)論,以及一些其他有趣小東西。

聲明,本文中顯示的示例是零碎的(片面的,只能體現(xiàn)相關(guān)的信息); 數(shù)據(jù)庫訪問、外部緩存系統(tǒng)( memcache 等等)以及任何需要 I/O 的東西都將執(zhí)行某種類型的 I/O 調(diào)用,其實質(zhì)與上面所示的簡單示例效果相同。此外,對于將 I/O 描述為“阻塞”( PHP、Java )的情況,HTTP 請求和響應(yīng)讀取和寫入本身就是阻塞調(diào)用:系統(tǒng)中隱藏著更多 I/O 及其伴生的性能問題需要考慮。

為一個項目選擇編程語言要考慮很多因素。甚至當(dāng)你只考慮效率時,也有很多因素。但是,如果你擔(dān)心你的程序?qū)⒅饕艿?I/O 的限制,如果 I/O 性能影響到項目的成敗,那么這些是你需要了解的。

“保持簡單”方法:PHP

早在 90 年代,很多人都穿著 Converse 鞋,用 Perl 寫著 CGI 腳本。然后 PHP 來了,就像一些人喜歡咒罵的一樣,它使得動態(tài)網(wǎng)頁更容易。

PHP 使用的模型相當(dāng)簡單。雖有一些出入,但你的 PHP 服務(wù)器基本上是這樣:

HTTP 請求來自用戶的瀏覽器,并訪問你的 Apache Web 服務(wù)器。Apache 為每個請求創(chuàng)建一個單獨的進程,有一些優(yōu)化方式可以重新使用它們,以***限度地減少創(chuàng)建次數(shù)( 相對而言,創(chuàng)建進程較慢 )。Apache 調(diào)用 PHP 并告訴它運行磁盤上合適的 .php 文件。PHP 代碼執(zhí)行并阻塞 I/O 調(diào)用。你在 PHP 中調(diào)用 file_get_contents() ,其底層會調(diào)用 read() 系統(tǒng)調(diào)用并等待結(jié)果。

當(dāng)然,實際的代碼是直接嵌入到你的頁面,并且該操作被阻塞:

  1. <?php 
  2. // blocking file I/O 
  3. $file_data = file_get_contents(‘/path/to/file.dat’); 
  4. // blocking network I/O 
  5. $curl = curl_init('http://example.com/example-microservice'); 
  6. $result = curl_exec($curl); 
  7. // some more blocking network I/O 
  8. $result = $db->query('SELECT id, data FROM examples ORDER BY id DESC limit 100'); 
  9. ?> 

關(guān)于如何與系統(tǒng)集成,就像這樣:

 

I/O Model PHP

很簡單:每個請求一個進程。 I/O 調(diào)用就阻塞。優(yōu)點是簡單可工作,缺點是,同時與 20,000 個客戶端連接,你的服務(wù)器將會崩潰。這種方法不能很好地擴展,因為內(nèi)核提供的用于處理大容量 I/O (epoll 等) 的工具沒有被使用。 雪上加霜的是,為每個請求運行一個單獨的進程往往會使用大量的系統(tǒng)資源,特別是內(nèi)存,這通常是你在這樣的場景中遇到的***個問題。

注意:Ruby 使用的方法與 PHP 非常相似,在大致的方面上,它們可以被認(rèn)為是相同的。

多線程方法: Java

就在你購買你的***個域名,在某個句子后很酷地隨機說出 “dot com” 的那個時候,Java 來了。而 Java 具有內(nèi)置于該語言中的多線程功能,它非常棒(特別是在創(chuàng)建時)。

大多數(shù) Java Web 服務(wù)器通過為每個請求啟動一個新的執(zhí)行線程,然后在該線程中最終調(diào)用你(作為應(yīng)用程序開發(fā)人員)編寫的函數(shù)。

在 Java Servlet 中執(zhí)行 I/O 往往看起來像:

  1. public void doGet(HttpServletRequest request, 
  2.     HttpServletResponse response) throws ServletException, IOException 
  3.     // blocking file I/O 
  4.     InputStream fileIs = new FileInputStream("/path/to/file"); 
  5.     // blocking network I/O 
  6.     URLConnection urlConnection = (new URL("http://example.com/example-microservice")).openConnection(); 
  7.     InputStream netIs = urlConnection.getInputStream(); 
  8.     // some more blocking network I/O 
  9. out.println("..."); 

由于我們上面的 doGet 方法對應(yīng)于一個請求,并且在其自己的線程中運行,而不是每個請求一個單獨的進程,申請自己的內(nèi)存。這樣有一些好處,比如在線程之間共享狀態(tài)、緩存數(shù)據(jù)等,因為它們可以訪問彼此的內(nèi)存,但是它與調(diào)度的交互影響與之前的 PHP 的例子幾乎相同。每個請求獲得一個新線程,該線程內(nèi)的各種 I/O 操作阻塞在線程內(nèi),直到請求被完全處理為止。線程被池化以最小化創(chuàng)建和銷毀它們的成本,但是數(shù)千個連接仍然意味著數(shù)千個線程,這對調(diào)度程序是不利的。

重要的里程碑出現(xiàn)在 Java 1.4 版本(以及 1.7 的重要升級)中,它獲得了執(zhí)行非阻塞 I/O 調(diào)用的能力。大多數(shù)應(yīng)用程序、web 應(yīng)用和其它用途不會使用它,但至少它是可用的。一些 Java Web 服務(wù)器嘗試以各種方式利用這一點;然而,絕大多數(shù)部署的 Java 應(yīng)用程序仍然如上所述工作。

 

I/O Model Java

肯定有一些很好的開箱即用的 I/O 功能,Java 讓我們更接近,但它仍然沒有真正解決當(dāng)你有一個大量的 I/O 綁定的應(yīng)用程序被數(shù)千個阻塞線程所壓垮的問題。

無阻塞 I/O 作為一等公民: Node

當(dāng)更好的 I/O 模式來到 Node.js,阻塞才真正被解決。任何一個曾聽過 Node 簡單介紹的人都被告知這是“非阻塞”,可以有效地處理 I/O。這在一般意義上是正確的。但在細(xì)節(jié)中則不盡然,而且當(dāng)在進行性能工程時,這種巫術(shù)遇到了問題。

Node 實現(xiàn)的范例基本上不是說 “在這里寫代碼來處理請求”,而是說 “在這里寫代碼來開始處理請求”。每次你需要做一些涉及到 I/O 的操作,你會創(chuàng)建一個請求并給出一個回調(diào)函數(shù),Node 將在完成之后調(diào)用該函數(shù)。

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

  1. http.createServer(function(request, response) { 
  2.     fs.readFile('/path/to/file''utf8'function(err, data) { 
  3.         response.end(data); 
  4.     }); 
  5. }); 

你可以看到,這里有兩個回調(diào)函數(shù)。當(dāng)請求開始時,***個被調(diào)用,當(dāng)文件數(shù)據(jù)可用時,第二個被調(diào)用。

這樣做的基本原理是讓 Node 有機會有效地處理這些回調(diào)之間的 I/O 。一個更加密切相關(guān)的場景是在 Node 中進行數(shù)據(jù)庫調(diào)用,但是我不會在這個例子中啰嗦,因為它遵循完全相同的原則:啟動數(shù)據(jù)庫調(diào)用,并給 Node 一個回調(diào)函數(shù),它使用非阻塞調(diào)用單獨執(zhí)行 I/O 操作,然后在你要求的數(shù)據(jù)可用時調(diào)用回調(diào)函數(shù)。排隊 I/O 調(diào)用和讓 Node 處理它然后獲取回調(diào)的機制稱為“事件循環(huán)”。它工作的很好。 

 

I/O Model Node.js

然而,這個模型有一個陷阱,究其原因,很多是與 V8 JavaScript 引擎(Node 用的是 Chrome 瀏覽器的 JS 引擎)如何實現(xiàn)的有關(guān)注1 。你編寫的所有 JS 代碼都運行在單個線程中。你可以想想,這意味著當(dāng)使用高效的非阻塞技術(shù)執(zhí)行 I/O 時,你的 JS 可以在單個線程中運行計算密集型的操作,每個代碼塊都會阻塞下一個。可能出現(xiàn)這種情況的一個常見例子是以某種方式遍歷數(shù)據(jù)庫記錄,然后再將其輸出到客戶端。這是一個示例,展示了其是如何工作:

  1. var handler = function(request, response) { 
  2.     connection.query('SELECT ...'function (err, rows) { 
  3.         if (err) { throw err }; 
  4.         for (var i = 0; i < rows.length; i++) { 
  5.             // do processing on each row 
  6.         } 
  7.         response.end(...); // write out the results 
  8.     }) 
  9. }; 

雖然 Node 確實有效地處理了 I/O ,但是上面的例子中 for 循環(huán)是在你的唯一的一個主線程中占用 CPU 周期。這意味著如果你有 10,000 個連接,則該循環(huán)可能會使你的整個應(yīng)用程序像爬行般緩慢,具體取決于其會持續(xù)多久。每個請求必須在主線程中分享一段時間,一次一段。

這整個概念的前提是 I/O 操作是最慢的部分,因此最重要的是要有效地處理這些操作,即使這意味著要連續(xù)進行其他處理。這在某些情況下是正確的,但不是全部。

另一點是,雖然這只是一個觀點,但是寫一堆嵌套的回調(diào)可能是相當(dāng)令人討厭的,有些則認(rèn)為它使代碼更難以追蹤。在 Node 代碼中看到回調(diào)嵌套 4 層、5 層甚至更多層并不罕見。

我們再次來權(quán)衡一下。如果你的主要性能問題是 I/O,則 Node 模型工作正常。然而,它的關(guān)鍵是,你可以在一個處理 HTTP 請求的函數(shù)里面放置 CPU 密集型的代碼,而且不小心的話會導(dǎo)致每個連接都很慢。

最自然的非阻塞:Go

在我進入 Go 部分之前,我應(yīng)該披露我是一個 Go 的粉絲。我已經(jīng)在許多項目中使用過它,我是一個其生產(chǎn)力優(yōu)勢的公開支持者,我在我的工作中使用它。

那么,讓我們來看看它是如何處理 I/O 的。Go 語言的一個關(guān)鍵特征是它包含自己的調(diào)度程序。在 Go 中,不是每個執(zhí)行線程對應(yīng)于一個單一的 OS 線程,其通過一種叫做 “協(xié)程goroutine” 的概念來工作。而 Go 的運行時可以將一個協(xié)程分配給一個 OS 線程,使其執(zhí)行或暫停它,并且它不與一個 OS 線程相關(guān)聯(lián)——這要基于那個協(xié)程正在做什么。來自 Go 的 HTTP 服務(wù)器的每個請求都在單獨的協(xié)程中處理。

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

 

I/O Model Go

在底層,這是通過 Go 運行時中的各個部分實現(xiàn)的,它通過對請求的寫入/讀取/連接等操作來實現(xiàn) I/O 調(diào)用,將當(dāng)前協(xié)程休眠,并當(dāng)采取進一步動作時喚醒該協(xié)程。

從效果上看,Go 運行時做的一些事情與 Node 做的沒有太大不同,除了回調(diào)機制是內(nèi)置到 I/O 調(diào)用的實現(xiàn)中,并自動與調(diào)度程序交互。它也不會受到必須讓所有處理程序代碼在同一個線程中運行的限制,Go 將根據(jù)其調(diào)度程序中的邏輯自動將協(xié)程映射到其認(rèn)為適當(dāng)?shù)?OS 線程。結(jié)果是這樣的代碼:

  1. func ServeHTTP(w http.ResponseWriter, r *http.Request) { 
  2.     // the underlying network call here is non-blocking 
  3.     rows, err := db.Query("SELECT ..."
  4.     for _, row := range rows { 
  5.         // do something with the rows
  6. // each request in its own goroutine 
  7.     } 
  8.     w.Write(...) // write the response, also non-blocking 

如上所述,我們重構(gòu)基本的代碼結(jié)構(gòu)為更簡化的方式,并在底層仍然實現(xiàn)了非阻塞 I/O。

在大多數(shù)情況下,最終是“兩全其美”的。非阻塞 I/O 用于所有重要的事情,但是你的代碼看起來像是阻塞,因此更容易理解和維護。Go 調(diào)度程序和 OS 調(diào)度程序之間的交互處理其余部分。這不是完整的魔法,如果你建立一個大型系統(tǒng),那么值得我們來看看有關(guān)它的工作原理的更多細(xì)節(jié);但與此同時,你獲得的“開箱即用”的環(huán)境可以很好地工作和擴展。

Go 可能有其缺點,但一般來說,它處理 I/O 的方式不在其中。

謊言,可惡的謊言和基準(zhǔn)

對這些各種模式的上下文切換進行準(zhǔn)確的定時是很困難的。我也可以認(rèn)為這對你來說不太有用。相反,我會給出一些比較這些服務(wù)器環(huán)境的整個 HTTP 服務(wù)器性能的基本基準(zhǔn)。請記住,影響整個端到端 HTTP 請求/響應(yīng)路徑的性能有很多因素,這里提供的數(shù)字只是我將一些樣本放在一起進行基本比較的結(jié)果。

對于這些環(huán)境中的每一個,我寫了適當(dāng)?shù)拇a在一個 64k 文件中讀取隨機字節(jié),在其上運行了一個 SHA-256 哈希 N 次( N 在 URL 的查詢字符串中指定,例如 .../test.php?n=100),并打印出結(jié)果十六進制散列。我選擇這樣做,是因為使用一些一致的 I/O 和受控的方式來運行相同的基準(zhǔn)測試是一個增加 CPU 使用率的非常簡單的方法。

有關(guān)使用的環(huán)境的更多細(xì)節(jié),請參閱 基準(zhǔn)說明 。

首先,我們來看一些低并發(fā)的例子。運行 2000 次迭代,300 個并發(fā)請求,每個請求只有一個散列(N = 1),結(jié)果如下:

 

時間是在所有并發(fā)請求中完成請求的平均毫秒數(shù)。越低越好。

僅從一張圖很難得出結(jié)論,但是對我來說,似乎在大量的連接和計算量上,我們看到時間更多地與語言本身的一般執(zhí)行有關(guān),對于 I/O 更是如此。請注意,那些被視為“腳本語言”的語言(松散類型,動態(tài)解釋)執(zhí)行速度最慢。

但是,如果我們將 N 增加到 1000,仍然有 300 個并發(fā)請求,相同的任務(wù),但是哈希迭代是 1000 倍(顯著增加了 CPU 負(fù)載): 

 

時間是在所有并發(fā)請求中完成請求的平均毫秒數(shù)。越低越好。

突然間, Node 性能顯著下降,因為每個請求中的 CPU 密集型操作都相互阻塞。有趣的是,在這個測試中,PHP 的性能要好得多(相對于其他的),并且打敗了 Java。(值得注意的是,在 PHP 中,SHA-256 實現(xiàn)是用 C 編寫的,在那個循環(huán)中執(zhí)行路徑花費了更多的時間,因為現(xiàn)在我們正在進行 1000 個哈希迭代)。

現(xiàn)在讓我們嘗試 5000 個并發(fā)連接(N = 1) - 或者是我可以發(fā)起的***連接。不幸的是,對于大多數(shù)這些環(huán)境,故障率并不顯著。對于這個圖表,我們來看每秒的請求總數(shù)。 越高越好 :

 

每秒請求數(shù)。越高越好。

這個圖看起來有很大的不同。我猜測,但是看起來像在高連接量時,產(chǎn)生新進程所涉及的每連接開銷以及與 PHP + Apache 相關(guān)聯(lián)的附加內(nèi)存似乎成為主要因素,并阻止了 PHP 的性能。顯然,Go 是這里的贏家,其次是 Java,Node,***是 PHP。

雖然與你的整體吞吐量相關(guān)的因素很多,并且在應(yīng)用程序之間也有很大的差異,但是你對底層發(fā)生什么的事情以及所涉及的權(quán)衡了解更多,你將會得到更好的結(jié)果。

總結(jié)

以上所有這一切,很顯然,隨著語言的發(fā)展,處理大量 I/O 的大型應(yīng)用程序的解決方案也隨之發(fā)展。

為了公平起見,PHP 和 Java,盡管這篇文章中的描述,確實 實現(xiàn)了 在 web 應(yīng)用程序 中 可使用的 非阻塞 I/O 。但是這些方法并不像上述方法那么常見,并且需要考慮使用這種方法來維護服務(wù)器的隨之而來的操作開銷。更不用說你的代碼必須以與這些環(huán)境相適應(yīng)的方式進行結(jié)構(gòu)化;你的 “正常” PHP 或 Java Web 應(yīng)用程序通常不會在這樣的環(huán)境中進行重大修改。

作為比較,如果我們考慮影響性能和易用性的幾個重要因素,我們得出以下結(jié)論: 

 

< 如顯示不全,請左右滑動 >
語言 線程與進程 非阻塞 I/O 使用便捷性
PHP 進程  
Java 線程 可用 需要回調(diào)
Node.js 線程 需要回調(diào)
Go 線程 (協(xié)程) 不需要回調(diào)

 

線程通常要比進程有更高的內(nèi)存效率,因為它們共享相同的內(nèi)存空間,而進程則沒有。結(jié)合與非阻塞 I/O 相關(guān)的因素,我們可以看到,至少考慮到上述因素,當(dāng)我們從列表往下看時,與 I/O 相關(guān)的一般設(shè)置得到改善。所以如果我不得不在上面的比賽中選擇一個贏家,那肯定會是 Go。

即使如此,在實踐中,選擇構(gòu)建應(yīng)用程序的環(huán)境與你的團隊對所述環(huán)境的熟悉程度以及你可以實現(xiàn)的總體生產(chǎn)力密切相關(guān)。因此,每個團隊都深入并開始在 Node 或 Go 中開發(fā) Web 應(yīng)用程序和服務(wù)可能就沒有意義。事實上,尋找開發(fā)人員或你內(nèi)部團隊的熟悉度通常被認(rèn)為是不使用不同語言和/或環(huán)境的主要原因。也就是說,過去十五年來,時代已經(jīng)發(fā)生了變化。

希望以上內(nèi)容可以幫助你更清楚地了解底層發(fā)生的情況,并為你提供如何處理應(yīng)用程序的現(xiàn)實可擴展性的一些想法。 

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2021-07-11 06:43:29

服務(wù)端Node路由

2020-06-10 08:28:51

Kata容器I

2021-05-07 17:46:53

存儲IO

2009-12-04 13:50:00

PHP服務(wù)端返回Jso

2023-07-12 08:24:19

Java NIO通道

2022-04-23 16:30:22

Linux磁盤性能

2010-03-19 18:17:17

Java Server

2024-02-01 12:12:01

2024-11-01 11:46:59

2024-05-27 00:00:00

PHP阿里云OSS

2011-08-05 13:41:46

Go

2016-03-18 09:04:42

swift服務(wù)端

2013-05-14 09:31:06

IBM閃存服務(wù)器

2024-03-05 18:24:52

I/O聚合優(yōu)化存儲

2023-05-08 00:06:45

Go語言機制

2010-03-18 18:09:36

Java Socket

2022-05-22 13:55:30

Go 語言

2013-05-28 10:08:41

IO輸出

2017-09-07 12:35:39

前端JavascriptNode.js

2024-11-29 09:47:44

AprEndpoin組件
點贊
收藏

51CTO技術(shù)棧公眾號