Node.js 究竟是什麼?
轉自:http://www.ibm.com/developerworks/cn/opensource/os-nodejs/index.html?ca=drs-
如果您聽說過 Node,或者閱讀過一些文章,宣稱 Node 是多麼多麼的棒,那麼您可能會想:“Node 究竟是什麼東西?” 即便是在參閱 Node 的主頁之後,您甚至可能還是 不明白 Node 為何物?Node 肯定不適合每個程式設計師,但它可能是某些程式設計師一直苦苦追尋的東西。
為試圖解釋什麼是 Node.js,本文將簡要介紹一些背景資訊:它要解決的問題,它如何工作,如何執行一個簡單應用程式,最後,Node 在什麼情況下是一個好的解決方案。本文不涉及如何編寫一個複雜的 Node 應用程式,也不是一份全面的 Node 教程。閱讀本文應該有助於您決定是否應該繼續學習 Node,以便將其用於您的業務。
Node 公開宣稱的目標是 “旨在提供一種簡單的構建可伸縮網路程式的方法”。當前的伺服器程式有什麼問題?我們來做個數學題。在 Java™ 和 PHP 這類語言中,每個連線都會生成一個新執行緒,每個新執行緒可能需要 2 MB 的配套記憶體。在一個擁有 8 GB RAM 的系統上,理論上最大的併發連線數量是 4,000 個使用者。隨著您的客戶群的增長,如果希望您的 Web 應用程式支援更多使用者,那麼,您必須新增更多伺服器。當然,這會增加伺服器成本、流量成本和人工成本等成本。除這些成本上升外,還有一個潛在技術問題,即使用者可能針對每個請求使用不同的伺服器,因此,任何共享資源都必須在所有伺服器之間共享。鑑於上述所有原因,整個 Web 應用程式架構(包括流量、處理器速度和記憶體速度)中的瓶頸是:伺服器能夠處理的併發連線的最大數量。
Node 解決這個問題的方法是:更改連線到伺服器的方式。每個連線發射一個在 Node 引擎的程式中執行的事件,而不是為每個連線生成一個新的 OS 執行緒(併為其分配一些配套記憶體)。Node 聲稱它絕不會死鎖,因為它根本不允許使用鎖,它不會直接阻塞 I/O 呼叫。Node 還宣稱,執行它的伺服器能支援數萬個併發連線。
現在您有了一個能處理數萬個併發連線的程式,那麼您能通過 Node 實際構建什麼呢?如果您有一個 Web 應用程式需要處理這麼多連線,那將是一件很 “恐怖” 的事!那是一種 “如果您有這個問題,那麼它根本不是問題” 的問題。在回答上面的問題之前,我們先看看 Node 的工作原理以及它的設計執行方式。
沒錯,Node 是一個伺服器程式。但是,基礎 Node 產品肯定不 像 Apache 或 Tomcat。本質上,那些伺服器 “安裝就緒型” 伺服器產品,支援立即部署應用程式。通過這些產品,您可以在一分鐘內啟動並執行一個伺服器。Node 肯定不是這種產品。Apache 能通過新增一個 PHP 模組來允許開發人員建立動態 Web 頁,新增一個 SSL 模組來實現安全連線,與此類似,Node 也有模組概念,允許向 Node 核心新增模組。實際上,可供選擇的用於 Node 的模組有數百個之多,社群在建立、釋出和更新模組方面非常活躍,一天甚至可以處理數十個模組。本文後面將討論 Node 的整個模組部分。
Node 本身執行 V8 JavaScript。等等,伺服器上的 JavaScript?沒錯,您沒有看錯。對於只在客戶機上使用 JavaScript 的程式設計師而言,伺服器端 JavaScript 可能是一個新概念,但這個概念本身並非遙不可及,因此為何不能在伺服器上使用客戶機上使用的程式語言?
什麼是 V8?V8 JavaScript 引擎是 Google 用於其 Chrome 瀏覽器的底層 JavaScript 引擎。很少有人考慮 JavaScript 在客戶機上實際做了些什麼?實際上,JavaScript 引擎負責解釋並執行程式碼。Google 使用 V8 建立了一個用 C++ 編寫的超快直譯器,該直譯器擁有另一個獨特特徵;您可以下載該引擎並將其嵌入任何 應用程式。V8 JavaScript 引擎並不僅限於在一個瀏覽器中執行。因此,Node 實際上會使用 Google 編寫的 V8 JavaScript 引擎,並將其重建為可在伺服器上使用。太完美了!既然已經有一個不錯的解決方案可用,為何還要建立一種新語言呢?
許多程式設計師接受的教育使他們認為,物件導向程式設計是完美的程式設計設計,這使得他們對其他程式設計方法不屑一顧。Node 使用了一個所謂的事件驅動程式設計模型。
// jQuery code on the client-side showing how Event-Driven programming works // When a button is pressed, an Event occurs - deal with it // directly right here in an anonymous function, where all the // necessary variables are present and can be referenced directly $("#myButton").click(function(){ if ($("#myTextField").val() != $(this).val()) alert("Field must match button text"); }); |
實際上,伺服器端和客戶端沒有任何區別。沒錯,這沒有按鈕點選操作,也沒有向文字欄位鍵入的操作,但在一個更高的層面上,事件正在 發生。一個連線被建立,這是一個事件!資料通過連線進行接收,這也是一個事件!資料通過連線停止,這還是一個事件!
為什麼這種設定型別對 Node 很理想?JavaScript 是一種很棒的事件驅動程式語言,因為它允許使用匿名函式和閉包,更重要的是,任何寫過程式碼的人都熟悉它的語法。事件發生時呼叫的回撥函式可以在捕獲事件處進行編寫。這樣可以使程式碼容易編寫和維護,沒有複雜的物件導向框架,沒有介面,沒有過度設計的可能性。只需監聽事件,編寫一個回撥函式,其他事情都可以交給系統處理!
最後,我們來看一些程式碼!讓我們將討論過的所有內容彙總起來,從而建立我們的第一個 Node 應用程式。我們已經知道,Node 對於處理高流量應用程式很理想,所以我們將建立一個非常簡單的 Web 應用程式,一個為實現最快速度而構建的應用程式。下面是 “老闆” 交代的關於我們的樣例應用程式的具體要求:建立一個隨機數字生成器 RESTful API。這個應用程式應該接受一個輸入:一個名為 “number” 的引數。然後,應用程式返回一個介於 0 和該引數之間的隨機數字,並將生成的數字返回給呼叫者。由於 “老闆” 希望該應用程式成為一個廣泛流行的應用程式,因此它應該能處理 50,000 個併發使用者。我們來看看以下程式碼:
// these modules need to be imported in order to use them. // Node has several modules. They are like any #include // or import statement in other languages var http = require("http"); var url = require("url"); // The most important line in any Node file. This function // does the actual process of creating the server. Technically, // Node tells the underlying operating system that whenever a // connection is made, this particular callback function should be // executed. Since we're creating a web service with REST API, // we want an HTTP server, which requires the http variable // we created in the lines above. // Finally, you can see that the callback method receives a 'request' // and 'response' object automatically. This should be familiar // to any PHP or Java programmer. http.createServer(function(request, response) { // The response needs to handle all the headers, and the return codes // These types of things are handled automatically in server programs // like Apache and Tomcat, but Node requires everything to be done yourself response.writeHead(200, {"Content-Type": "text/plain"}); // Here is some unique-looking code. This is how Node retrives // parameters passed in from client requests. The url module // handles all these functions. The parse function // deconstructs the URL, and places the query key-values in the // query object. We can find the value for the "number" key // by referencing it directly - the beauty of JavaScript. var params = url.parse(request.url, true).query; var input = params.number; // These are the generic JavaScript methods that will create // our random number that gets passed back to the caller var numInput = new Number(input); var numOutput = new Number(Math.random() * numInput).toFixed(0); // Write the random number to response response.write(numOutput); // Node requires us to explicitly end this connection. This is because // Node allows you to keep a connection open and pass data back and forth, // though that advanced topic isn't discussed in this article. response.end(); // When we create the server, we have to explicitly connect the HTTP server to // a port. Standard HTTP port is 80, so we'll connect it to that one. }).listen(80); // Output a String to the console once the server starts up, letting us know everything // starts up correctly console.log("Random Number Generator Running..."); |
將上面的程式碼放入一個名為 “random.js” 的檔案中。現在,要啟動這個應用程式並執行它(以便建立 HTTP 伺服器並監聽埠 80 上的連線),只需在您的命令提示中輸入以下命令:% node random.js
。下面是伺服器已經啟動並執行時看起來的樣子:
root@ubuntu:/home/moila/ws/mike# node random.js Random Number Generator Running... |
應用程式已經啟動並執行。Node 正在監聽所有連線,我們來測試一下。由於我們建立了一個簡單的 RESTful API,所以可以使用 Web 瀏覽器來訪問這個應用程式。鍵入以下地址(確保您已完成了上面的步驟):http://localhost/?number=27。
您的瀏覽器視窗將更改到一個介於 0 到 27 之間的隨機數字。單擊瀏覽器上的 “重新載入” 按鈕,您會得到另一個隨機數字。就是這樣,這就是您的第一個 Node 應用程式!
到此為止,您可能能夠回答 “Node 是什麼” 這個問題了,但您可能還有一個問題:“Node 有什麼用途?” 這是一個需要提出的重要問題,因為肯定有些東西能受益於 Node。
正如您此前所看到的,Node 非常適合以下情況:在響應客戶端之前,您預計可能有很高的流量,但所需的伺服器端邏輯和處理不一定很多。Node 表現出眾的典型示例包括:
- RESTful API
提供 RESTful API 的 Web 服務接收幾個引數,解析它們,組合一個響應,並返回一個響應(通常是較少的文字)給使用者。這是適合 Node 的理想情況,因為您可以構建它來處理數萬條連線。它仍然不需要大量邏輯;它本質上只是從某個資料庫中查詢一些值並將它們組成一個響應。由於響應是少量文字,入站請求也是少量的文字,因此流量不高,一臺機器甚至也可以處理最繁忙的公司的 API 需求。
- Twitter 佇列
想像一下像 Twitter 這樣的公司,它必須接收 tweets 並將其寫入資料庫。實際上,每秒幾乎有數千條 tweet 達到,資料庫不可能及時處理高峰時段所需的寫入數量。Node 成為這個問題的解決方案的重要一環。如您所見,Node 能處理數萬條入站 tweet。它能快速而又輕鬆地將它們寫入一個記憶體排隊機制(例如 memcached),另一個單獨程式可以從那裡將它們寫入資料庫。Node 在這裡的角色是迅速收集 tweet,並將這個資訊傳遞給另一個負責寫入的程式。想象一下另一種設計(常規 PHP 伺服器會自己嘗試處理對資料庫本身的寫入):每個 tweet 都會在寫入資料庫時導致一個短暫的延遲,因為資料庫呼叫正在阻塞通道。由於資料庫延遲,一臺這樣設計的機器每秒可能只能處理 2000 條入站 tweet。每秒處理 100 萬條 tweet 則需要 500 個伺服器。相反,Node 能處理每個連線而不會阻塞通道,從而能夠捕獲儘可能多的 tweets。一個能處理 50,000 條 tweet 的 Node 機器僅需 20 臺伺服器即可。
- 電子遊戲統計資料
如果您線上玩過《使命召喚》這款遊戲,當您檢視遊戲統計資料時,就會立即意識到一個問題:要生成那種級別的統計資料,必須跟蹤海量資訊。這樣,如果有數百萬玩家同時線上玩遊戲,而且他們處於遊戲中的不同位置,那麼很快就會生成海量資訊。Node 是這種場景的一種很好的解決方案,因為它能採集遊戲生成的資料,對資料進行最少的合併,然後對資料進行排隊,以便將它們寫入資料庫。使用整個伺服器來跟蹤玩家在遊戲中發射了多少子彈看起來很愚蠢,如果您使用 Apache 這樣的伺服器,可能會有一些有用的限制;但相反,如果您專門使用一個伺服器來跟蹤一個遊戲的所有統計資料,就像使用執行 Node 的伺服器所做的那樣,那看起來似乎是一種明智之舉。
儘管不是本文最初計劃討論的主題,但應廣大讀者要求,本文已經擴充套件為包含一個 Node Modules 和 Node Package Manager 簡介。正如已經習慣使用 Apache 的開發人員那樣,您也可以通過安裝模組來擴充套件 Node 的功能。但是,可用於 Node 的模組極大地 增強了這個產品,那些模組非常有用,將使用 Node 的開發人員通常會安裝幾個模組。因此,模組也就變得越來越重要,甚至成為整個產品的一個關鍵部分。
在 “參考資料” 部分,我提供了一個指向模組頁面的連結,該頁面列示了所有可用模組。為了展示模組能夠提供的可能性,我在數十個可用模組中包含了以下幾個模組:一個用於編寫動態建立的頁面(比如 PHP),一個用於簡化 MySQL 使用,一個用於幫助使用 WebSockets,還有一個用來協助文字和引數解析的模組。我不會詳細介紹這些模組,這是因為這篇概述文章旨在幫助您瞭解 Node 並確定是否需要深入學習(再次重申),如果需要,那麼您肯定有機會用到這些可用模組。
另外,Node 的一個特性是 Node Package Module,這是一個內建功能,用於安裝和管理 Node 模組。它自動處理依賴項,因此您可以確定:您想要安裝的任何模組都將正確安裝幷包含必要的依賴項。它還支援將您自己的模組釋出到 Node 社群,假如您選擇加入社群並編寫自己的模組的話。您可以將 NPM 視為一種允許輕鬆擴充套件 Node 功能的方法,不必擔心這會破壞您的 Node 安裝。同樣,如果您選擇深入學習 Node,那麼 NPM 將是您的 Node 解決方案的一個重要組成部分。
閱讀本文之後,您在本文開頭遇到的問題 “Node.js 究竟是什麼東西?” 應該已經得到了解答,您應該能通過幾個清晰簡潔的句子回答這個問題。如果這樣,那麼您已經走到了許多程式設計師的前面。我和許多人都談論過 Node,但他們對 Node 究竟用於做什麼一直很迷惑。可以理解,他們具有的是 Apache 的思維方式,認為伺服器就是一個應用程式,將 HTML 檔案放入其中,一切就會正常運轉。由於大多數程式設計師都熟悉 Apache 及其用途,因此,描述 Node 的最簡單方法就是將它與 Apache 進行比較。Node 是一個程式,能夠完成 Apache 能夠完成的所有任務(藉助一些模組),而且,作為一個可以將其作為基礎進行構建的可擴充套件 JavaScript 平臺,Node 還能完成更多的任務。
從本文可以看出,Node 完成了它提供高度可伸縮伺服器的目標。它使用了 Google 的一個非常快速的 JavaScript 引擎,即 V8 引擎。它使用一個事件驅動設計來保持程式碼最小且易於閱讀。所有這些因素促成了 Node 的理想目標,即編寫一個高度可伸縮的解決方案變得比較容易。
與理解 Node 是 什麼同樣重要的是,理解它不是 什麼。Node 並不只是 Apache 的一個替代品,它旨在使 PHP Web 應用程式更容易伸縮。事實遠非如此。儘管 Node 還處於初始階段,但它發展得非常迅速,社群參與度非常高,社群成員建立了大量優秀模組,一年之內,這個不斷髮展的產品就有可能出現在您的企業中。
學習
- Node.js 主頁 是瞭解這個應用程式的切入點。
- 在這裡下載 Node.js。您還將需要
Python。
- 瀏覽 Node.js API 頁。注意,不同釋出的語法可能不同,因此,請仔細檢查您已下載的版本和正在瀏覽的 API。
- 參見 Node 模組頁,該頁列出了所有可用於 Node 中的模組。
- 搜尋 NPM,輕鬆擴充套件您的 Node 安裝的功能。
- 隨時關注 developerWorks
技術活動和網路廣播。
- 訪問 developerWorks
Open source 專區獲得豐富的 how-to 資訊、工具和專案更新以及最受歡迎的文章和教程,幫助您用開放原始碼技術進行開發,並將它們與 IBM 產品結合使用。
- 檢視免費的 developerWorks 演示中心,觀看並瞭解 IBM 及開源技術和產品功能。
相關文章
- Node.js 中的緩衝區(Buffer)究竟是什麼?Node.js
- # Apache SeaTunnel 究竟是什麼?Apache
- 《大前端進階 Node.js》系列 非同步非阻塞(阻塞究竟是指什麼?)前端Node.js非同步
- chmod 755 究竟是什麼鬼?
- [轉]DevOps究竟是什麼鬼?dev
- 伺服器究竟是什麼呢?伺服器
- 什麼是Node.jsNode.js
- 最近大火的「元宇宙」究竟是什麼元宇宙
- 人人都在談的Metaverse,究竟是什麼?Metaverse
- 區塊鏈應用開發究竟是什麼,有什麼用區塊鏈
- 為什麼用Node.js?Node.js
- 為什麼要用Node.jsNode.js
- 初識Node.js【01】Node.js是什麼?Node.js
- 訊息佇列究竟是個什麼鬼?佇列
- 大資料分析平臺究竟是什麼大資料
- 資料分類分級究竟是什麼
- 為什麼要使用Node.JSNode.js
- HTTP長連線、短連線究竟是什麼?HTTP
- 區塊鏈大火?區塊鏈究竟是什麼?區塊鏈
- IDP中的黃金路徑究竟是什麼?
- HTML5培訓究竟是學的什麼?HTML
- [原始碼解析] Flink的Slot究竟是什麼?(2)原始碼
- 恐怖遊戲究竟是用什麼嚇到你的?遊戲
- [原始碼解析] Flink的Slot究竟是什麼?(1)原始碼
- 大家都在聊的人工智慧,究竟是什麼?人工智慧
- Web技術:Token與Session究竟是什麼呢WebSession
- 鋪天蓋地的「雲原生」究竟是什麼?
- JS函數語言程式設計究竟是什麼?JS函數程式設計
- 市場聞之色變的DMA究竟是什麼
- Python中的類、模組和包究竟是什麼?Python
- C++ string的內部究竟是什麼樣的?C++
- 最近很火的低程式碼開發究竟是什麼?
- 為什麼 2020 還要學 Node.jsNode.js
- Node.js 是什麼以及如何學習?Node.js
- EA高管所說的“驚喜機制”究竟是什麼?
- 鐳速傳輸:不是格鬥術的MFT究竟是什麼?
- 什麼是挪車碼,掃碼挪車究竟是怎麼賺錢的?
- 什麼是KYC?與加密究竟是水火不容,還是可以兼得?加密
- 機器學習基礎:相似度和距離度量究竟是什麼機器學習