'為什麼要用 Node.js | Node.js Foundation 官方介紹'

"

介紹 JavaScript 的日益發展帶來了很多變化,當今的 Web 開發面貌已經變得截然不同。在幾年前是很難想象在服務器上運行 JavaScript 的。

在深入研究Node.js之前,你可能想了解使用跨棧的 JavaScript 有什麼好處,它統一了語言和數據格式(JSON),允許你以最佳的方式重用開發人員資源。將 Node.js 合併到技術棧中是一個關鍵優勢。

Node.js 是一個基於 Chrome 的名為 V8 的 JavaScript 引擎構建的 JavaScript 運行環境。值得注意的是,Node.js 的創建者 Ryan Dahl 的“受到 Gmail 等應用的啟發”,目標是為了開發一個具有實時推送功能的網站。在 Node.js 中,他提供了一個用於處理非阻塞事件驅動的 I/O 工具。

用一句話來概括:Node.js 在基於websockets 推送技術的實時 Web 應用中大放異彩。在過去的 20 多年來我們一直在使用基於無狀態請求 - 響應模式的無狀態 Web 應用,現在終於擁有了能夠實時雙向連接的 Web 應用,其中客戶端和服務器都可以啟動通信,並允許它們自由地交換數據。

這與典型的總是由客戶端發起通信的 Web 響應模式形了成鮮明的對比。此外它也同樣基於在標準端口 80 上運行的開放 Web 技術棧(HTML,CSS和JS)。

有人可能會爭辯說,我們多年來一直以 Flash 和 Java Applet 的形式做到這一點 —— 但實際上,這些只是使用 Web 作為傳輸協議將數據傳給客戶端的沙盒環境。此外,它們是隔離運行的,通常在非標準端口上運行,這可能需要額外的權限。

憑藉其優勢,Node.js 在依賴其獨特優勢的眾多知名公司的技術堆棧中發揮著關鍵作用。 Node.js 基金會幾乎已經整合了所有最好的想法,可以在 Node.js 基金會的案例研究頁面上找到關於為什麼企業應該考慮 Node.js 的簡短PPT。

在本文中,我將不僅要討論如何使用這些優勢,而且還要討論 為什麼 你可能想要使用 Node.js ,並用一些經典的 Web 應用程序模型作為示例。

它是如何工作的?

Node.js 的主要思想是:在面向跨分佈式設備運行的數據密集型的實時程序時,使用非阻塞、事件驅動的 I/O 來保證輕量和高效。

這讀起來很拗口。

這意味著 Node.js 不是 一個即將成為主宰 Web 開發界的能夠解決一切的新平臺。 **相反,它是一個滿足特定需求的平臺。**理解這一點絕對是有必要的。你絕不希望將 Node.js 用於 CPU 密集型的操作;實際上,將它用於進行大量繁重運算的場合將會消除它幾乎所有的優點。 Node.js 真正發揮作用的地方在於構建快速、可擴展的網絡應用,因為它能夠以高吞吐量處理大量兵法連接,這相當於具有高可擴展性。

其底層的工作原理非常有趣。傳統的 Web 服務技術每個連接(請求)都會產生一個新線程,佔用系統內存並最終受限於可用的最大內存,而 Node.js 在單線程上運行,使用非阻塞 I/O 調用,允許它支持數以萬計的併發連接(在 event loop 中維持)。

"

介紹 JavaScript 的日益發展帶來了很多變化,當今的 Web 開發面貌已經變得截然不同。在幾年前是很難想象在服務器上運行 JavaScript 的。

在深入研究Node.js之前,你可能想了解使用跨棧的 JavaScript 有什麼好處,它統一了語言和數據格式(JSON),允許你以最佳的方式重用開發人員資源。將 Node.js 合併到技術棧中是一個關鍵優勢。

Node.js 是一個基於 Chrome 的名為 V8 的 JavaScript 引擎構建的 JavaScript 運行環境。值得注意的是,Node.js 的創建者 Ryan Dahl 的“受到 Gmail 等應用的啟發”,目標是為了開發一個具有實時推送功能的網站。在 Node.js 中,他提供了一個用於處理非阻塞事件驅動的 I/O 工具。

用一句話來概括:Node.js 在基於websockets 推送技術的實時 Web 應用中大放異彩。在過去的 20 多年來我們一直在使用基於無狀態請求 - 響應模式的無狀態 Web 應用,現在終於擁有了能夠實時雙向連接的 Web 應用,其中客戶端和服務器都可以啟動通信,並允許它們自由地交換數據。

這與典型的總是由客戶端發起通信的 Web 響應模式形了成鮮明的對比。此外它也同樣基於在標準端口 80 上運行的開放 Web 技術棧(HTML,CSS和JS)。

有人可能會爭辯說,我們多年來一直以 Flash 和 Java Applet 的形式做到這一點 —— 但實際上,這些只是使用 Web 作為傳輸協議將數據傳給客戶端的沙盒環境。此外,它們是隔離運行的,通常在非標準端口上運行,這可能需要額外的權限。

憑藉其優勢,Node.js 在依賴其獨特優勢的眾多知名公司的技術堆棧中發揮著關鍵作用。 Node.js 基金會幾乎已經整合了所有最好的想法,可以在 Node.js 基金會的案例研究頁面上找到關於為什麼企業應該考慮 Node.js 的簡短PPT。

在本文中,我將不僅要討論如何使用這些優勢,而且還要討論 為什麼 你可能想要使用 Node.js ,並用一些經典的 Web 應用程序模型作為示例。

它是如何工作的?

Node.js 的主要思想是:在面向跨分佈式設備運行的數據密集型的實時程序時,使用非阻塞、事件驅動的 I/O 來保證輕量和高效。

這讀起來很拗口。

這意味著 Node.js 不是 一個即將成為主宰 Web 開發界的能夠解決一切的新平臺。 **相反,它是一個滿足特定需求的平臺。**理解這一點絕對是有必要的。你絕不希望將 Node.js 用於 CPU 密集型的操作;實際上,將它用於進行大量繁重運算的場合將會消除它幾乎所有的優點。 Node.js 真正發揮作用的地方在於構建快速、可擴展的網絡應用,因為它能夠以高吞吐量處理大量兵法連接,這相當於具有高可擴展性。

其底層的工作原理非常有趣。傳統的 Web 服務技術每個連接(請求)都會產生一個新線程,佔用系統內存並最終受限於可用的最大內存,而 Node.js 在單線程上運行,使用非阻塞 I/O 調用,允許它支持數以萬計的併發連接(在 event loop 中維持)。

為什麼要用 Node.js | Node.js Foundation 官方介紹

快速計算:假設每個線程需要 2 MB 內存,那麼在有 8 GB 內存的系統上運行的話,理論上最多有 4000 個併發連接*(計算來自 Michael Abernethy 的文章 “Just what is Node.js?“,2011年在 IBM developerWorks 上發佈;不幸的是,這篇文章的鏈接現在已經失效了)*,這還沒有算上線程之間的上下文切換的成本。這就是你通常在傳統的 Web 服務器技術中處理的場景。通過避免所有這些問題,Node.js 實現了超過 1M 連接併發數的級別,以及 600k 的 websockets 併發連接數。

當然,編寫 Node.js 應用的潛在缺陷是存在客戶端請求之間共享單個線程的問題。首先,繁重的計算可能會阻塞 Node 的單個線程並導致 所有 客戶端出現問題(稍後會詳細說明),因為傳入的請求將被阻塞,直到計算完成為止。其次開發人員需要 非常小心,不要讓異常冒泡到到核心(最頂層)Node.js 事件循環,這將導致 Node.js 實例終止(程序崩潰)。

為了避免異常冒泡到頂層,常用技術是將錯誤作為回調參數傳遞迴調用者(而不是像在其他環境中那樣拋出它們)。即使一些未被處理的異常冒泡到頂層,也有一些工具來監視 Node.js 進程並執行必要的恢復崩潰 (雖然可能無法恢復到用戶會話的當前狀態),最常見的是 Forever 模塊。

npm:node 包管理器

在討論 Node.js 時,一件絕對不應該被忽略的事是支持使用內置的 npm 工具進行包管理,默認情況下每個 Node.js 環境都會安裝。 npm 模塊的概念非常類似於 Ruby Gems:一組可通過在線存儲庫輕鬆安裝,具有版本和依賴關係管理的可重用組件,。

可以在 npm 網站上找到已打包模塊的完整列表,也可以使用自動與 Node.js 一起安裝的 npm CLI 工具進行訪問。模塊生態系統對所有人開放,任何人都可以發佈自己的模塊,發佈的模塊將出現在 npm 存儲庫中。有關 npm 的簡介,請參閱初學者指南,以及 npm 發佈教程中關於發佈模塊的部分。

一些很有用的 npm 模塊是:

  • express —— Express.js,一個受 Sinatra 啟發的 Node.js Web 開發框架,當今大多數 Node.js 應用程序的事實標準。
  • hapi —— 一個模塊化的且非常易於使用的以配置為中心的框架,用於構建 Web 和服務應用
  • connect —— Connect 是 Node.js 的可擴展 HTTP 服務器框架,提供了一系列稱為中間件的高性能“插件”作為Express的基礎。
  • socket.iosockjs —— 今天最常見的兩個 websockets 服務器端組件。
  • pug(以前叫 Jade)—— 受 HAML 啟發的流行模板引擎之一,Express.js 中的默認選項。
  • mongodbmongojs —— MongoDB 包裝器,為 Node.js 中的 MongoDB 對象數據庫提供 API。
  • redis —— Redis 客戶端。
  • forever —— 可能是確保給定 node 腳本連續運行的最常用實用程序。在遇到意外故障時,將 Node.js 的進程保持在生產狀態。
  • bluebird —— 功能齊全的 Promises/A+ 實現,性能非常出色
  • moment —— 用於解析、驗證、操作和格式化日期的輕量級 JavaScript 日期庫。

列表還在不斷增長。那裡有很多有用的包,可供所有人使用。

哪些場合應該使用 Node.js

在線聊天

在線聊天是最典型的實時多用戶應用,也是 Node.js 的最佳案例:它是一個輕量級、高流量、數據密集型(但是低處理和計算)的應用程序,可分佈式跨設備運行。它也是一個很好的學習案例,因為它很簡單,但涵蓋了你在典型的 Node.js 程序中所使用的大部分範例。

讓我們試著描繪它是如何工作的。

假設一個最簡單的場景,在我們的網站上有一個聊天室,人們可以通過一對多(實際上是對所有人)的方式交換消息。

在服務器端,我們有一個簡單的 Express.js 程序,它實現了兩件事:1) 一個GET 請求的處理程序,它提供了包含留言板和用於初始化新消息輸入的“發送”按鈕的功能,以及2) 用於偵聽 websocket 客戶端發出的新消息的w ebsockets 服務器。

在客戶端,我們有一個 HTML 頁面,其中設置了幾個處理程序,一個用於“發送”按鈕的單擊事件,它接收輸入消息並將其發送到 websocket,另一個用於偵聽新的傳入消息並顯示在 websockets 客戶端上(即服務器希望客戶端顯示的其他用戶發送的消息)。

當其中一個客戶發佈消息時,會發生以下情況:

  • 瀏覽器捕獲單擊“發送”按鈕事件處理 JavaScript 程序,從輸入字段(即消息文本)中獲取值,並使用連接到我們服務器的 websocket 客戶端發出 websocket 消息(在網頁初始化時初始化) 。
  • websocket 連接的服務器端組件接收消息,並使用廣播方式將其轉發給所有其他的客戶端。
  • 所有客戶端都通過在網頁中運行的 websockets 客戶端組件接收新消息。然後,他們通過將新消息添加頁面上並更新。
"

介紹 JavaScript 的日益發展帶來了很多變化,當今的 Web 開發面貌已經變得截然不同。在幾年前是很難想象在服務器上運行 JavaScript 的。

在深入研究Node.js之前,你可能想了解使用跨棧的 JavaScript 有什麼好處,它統一了語言和數據格式(JSON),允許你以最佳的方式重用開發人員資源。將 Node.js 合併到技術棧中是一個關鍵優勢。

Node.js 是一個基於 Chrome 的名為 V8 的 JavaScript 引擎構建的 JavaScript 運行環境。值得注意的是,Node.js 的創建者 Ryan Dahl 的“受到 Gmail 等應用的啟發”,目標是為了開發一個具有實時推送功能的網站。在 Node.js 中,他提供了一個用於處理非阻塞事件驅動的 I/O 工具。

用一句話來概括:Node.js 在基於websockets 推送技術的實時 Web 應用中大放異彩。在過去的 20 多年來我們一直在使用基於無狀態請求 - 響應模式的無狀態 Web 應用,現在終於擁有了能夠實時雙向連接的 Web 應用,其中客戶端和服務器都可以啟動通信,並允許它們自由地交換數據。

這與典型的總是由客戶端發起通信的 Web 響應模式形了成鮮明的對比。此外它也同樣基於在標準端口 80 上運行的開放 Web 技術棧(HTML,CSS和JS)。

有人可能會爭辯說,我們多年來一直以 Flash 和 Java Applet 的形式做到這一點 —— 但實際上,這些只是使用 Web 作為傳輸協議將數據傳給客戶端的沙盒環境。此外,它們是隔離運行的,通常在非標準端口上運行,這可能需要額外的權限。

憑藉其優勢,Node.js 在依賴其獨特優勢的眾多知名公司的技術堆棧中發揮著關鍵作用。 Node.js 基金會幾乎已經整合了所有最好的想法,可以在 Node.js 基金會的案例研究頁面上找到關於為什麼企業應該考慮 Node.js 的簡短PPT。

在本文中,我將不僅要討論如何使用這些優勢,而且還要討論 為什麼 你可能想要使用 Node.js ,並用一些經典的 Web 應用程序模型作為示例。

它是如何工作的?

Node.js 的主要思想是:在面向跨分佈式設備運行的數據密集型的實時程序時,使用非阻塞、事件驅動的 I/O 來保證輕量和高效。

這讀起來很拗口。

這意味著 Node.js 不是 一個即將成為主宰 Web 開發界的能夠解決一切的新平臺。 **相反,它是一個滿足特定需求的平臺。**理解這一點絕對是有必要的。你絕不希望將 Node.js 用於 CPU 密集型的操作;實際上,將它用於進行大量繁重運算的場合將會消除它幾乎所有的優點。 Node.js 真正發揮作用的地方在於構建快速、可擴展的網絡應用,因為它能夠以高吞吐量處理大量兵法連接,這相當於具有高可擴展性。

其底層的工作原理非常有趣。傳統的 Web 服務技術每個連接(請求)都會產生一個新線程,佔用系統內存並最終受限於可用的最大內存,而 Node.js 在單線程上運行,使用非阻塞 I/O 調用,允許它支持數以萬計的併發連接(在 event loop 中維持)。

為什麼要用 Node.js | Node.js Foundation 官方介紹

快速計算:假設每個線程需要 2 MB 內存,那麼在有 8 GB 內存的系統上運行的話,理論上最多有 4000 個併發連接*(計算來自 Michael Abernethy 的文章 “Just what is Node.js?“,2011年在 IBM developerWorks 上發佈;不幸的是,這篇文章的鏈接現在已經失效了)*,這還沒有算上線程之間的上下文切換的成本。這就是你通常在傳統的 Web 服務器技術中處理的場景。通過避免所有這些問題,Node.js 實現了超過 1M 連接併發數的級別,以及 600k 的 websockets 併發連接數。

當然,編寫 Node.js 應用的潛在缺陷是存在客戶端請求之間共享單個線程的問題。首先,繁重的計算可能會阻塞 Node 的單個線程並導致 所有 客戶端出現問題(稍後會詳細說明),因為傳入的請求將被阻塞,直到計算完成為止。其次開發人員需要 非常小心,不要讓異常冒泡到到核心(最頂層)Node.js 事件循環,這將導致 Node.js 實例終止(程序崩潰)。

為了避免異常冒泡到頂層,常用技術是將錯誤作為回調參數傳遞迴調用者(而不是像在其他環境中那樣拋出它們)。即使一些未被處理的異常冒泡到頂層,也有一些工具來監視 Node.js 進程並執行必要的恢復崩潰 (雖然可能無法恢復到用戶會話的當前狀態),最常見的是 Forever 模塊。

npm:node 包管理器

在討論 Node.js 時,一件絕對不應該被忽略的事是支持使用內置的 npm 工具進行包管理,默認情況下每個 Node.js 環境都會安裝。 npm 模塊的概念非常類似於 Ruby Gems:一組可通過在線存儲庫輕鬆安裝,具有版本和依賴關係管理的可重用組件,。

可以在 npm 網站上找到已打包模塊的完整列表,也可以使用自動與 Node.js 一起安裝的 npm CLI 工具進行訪問。模塊生態系統對所有人開放,任何人都可以發佈自己的模塊,發佈的模塊將出現在 npm 存儲庫中。有關 npm 的簡介,請參閱初學者指南,以及 npm 發佈教程中關於發佈模塊的部分。

一些很有用的 npm 模塊是:

  • express —— Express.js,一個受 Sinatra 啟發的 Node.js Web 開發框架,當今大多數 Node.js 應用程序的事實標準。
  • hapi —— 一個模塊化的且非常易於使用的以配置為中心的框架,用於構建 Web 和服務應用
  • connect —— Connect 是 Node.js 的可擴展 HTTP 服務器框架,提供了一系列稱為中間件的高性能“插件”作為Express的基礎。
  • socket.iosockjs —— 今天最常見的兩個 websockets 服務器端組件。
  • pug(以前叫 Jade)—— 受 HAML 啟發的流行模板引擎之一,Express.js 中的默認選項。
  • mongodbmongojs —— MongoDB 包裝器,為 Node.js 中的 MongoDB 對象數據庫提供 API。
  • redis —— Redis 客戶端。
  • forever —— 可能是確保給定 node 腳本連續運行的最常用實用程序。在遇到意外故障時,將 Node.js 的進程保持在生產狀態。
  • bluebird —— 功能齊全的 Promises/A+ 實現,性能非常出色
  • moment —— 用於解析、驗證、操作和格式化日期的輕量級 JavaScript 日期庫。

列表還在不斷增長。那裡有很多有用的包,可供所有人使用。

哪些場合應該使用 Node.js

在線聊天

在線聊天是最典型的實時多用戶應用,也是 Node.js 的最佳案例:它是一個輕量級、高流量、數據密集型(但是低處理和計算)的應用程序,可分佈式跨設備運行。它也是一個很好的學習案例,因為它很簡單,但涵蓋了你在典型的 Node.js 程序中所使用的大部分範例。

讓我們試著描繪它是如何工作的。

假設一個最簡單的場景,在我們的網站上有一個聊天室,人們可以通過一對多(實際上是對所有人)的方式交換消息。

在服務器端,我們有一個簡單的 Express.js 程序,它實現了兩件事:1) 一個GET 請求的處理程序,它提供了包含留言板和用於初始化新消息輸入的“發送”按鈕的功能,以及2) 用於偵聽 websocket 客戶端發出的新消息的w ebsockets 服務器。

在客戶端,我們有一個 HTML 頁面,其中設置了幾個處理程序,一個用於“發送”按鈕的單擊事件,它接收輸入消息並將其發送到 websocket,另一個用於偵聽新的傳入消息並顯示在 websockets 客戶端上(即服務器希望客戶端顯示的其他用戶發送的消息)。

當其中一個客戶發佈消息時,會發生以下情況:

  • 瀏覽器捕獲單擊“發送”按鈕事件處理 JavaScript 程序,從輸入字段(即消息文本)中獲取值,並使用連接到我們服務器的 websocket 客戶端發出 websocket 消息(在網頁初始化時初始化) 。
  • websocket 連接的服務器端組件接收消息,並使用廣播方式將其轉發給所有其他的客戶端。
  • 所有客戶端都通過在網頁中運行的 websockets 客戶端組件接收新消息。然後,他們通過將新消息添加頁面上並更新。
為什麼要用 Node.js | Node.js Foundation 官方介紹

這是最簡單的例子。對於更強大的解決方案,你可以使用基於 Redis 的簡單緩存。或者在更高級的解決方案中,可以用消息隊列作為消息路由,還可以實現更強大的傳遞機制,例如可以在連接丟失或在客戶端脫機時存儲消息。但無論你做出哪些改進,Node.js 仍將按照相同的基本原則運行:對事件做出反應,處理許多併發連接,並保持用戶體驗的流暢性。

對象數據庫頂層的 API

雖然 Node.js 的確很適合開發實時應用,但它也很適合從對象數據庫(例如MongoDB)公開數據。 JSON 存儲的數據允許 Node.js 在對象與存儲數據一致和沒有數據轉換的情況下良好的運行。

例如,如果你正在使用 Rails,那麼你需要從 JSON 轉換為二進制模型,然後通過 HTTP 再將它們轉為 JSON 在 React.js 或 Angular.js 中使用 ,甚至可以用簡單的 jQuery AJAX 進行調用。使用 Node.js,你可以通過 REST API 直接公開你的 JSON 對象來供客戶端使用。此外,在從數據庫讀取或寫入時(如果你使用的是MongoDB),你無需擔心在 JSON 和其他任何內容之間進行轉換的問題。總之在客戶端、服務器和數據庫中使用統一的數據序列化格式,可以避免多次轉換的麻煩。

隊列輸入

如果你收到了大量併發數據,那麼你的數據庫可能會成為瓶頸。如上所述,Node.js 可以輕鬆地自己處理併發連接。但是因為數據庫訪問是一種阻塞操作(在這種情況下),所以我們遇到了麻煩。解決方案是在數據真正寫入數據庫之前先確認客戶端的行為。

通過這種方法,系統可以在高負載下保持其響應性,這在客戶端不需要確認數據成功寫入時尤其有用。典型的例子包括:記錄或寫入用戶跟蹤數據時進行分批處理;以及最終一致性(經常在NoSQL世界中使用)可以接受的不需要立即作出反映的操作(例如更新 Facebook 上的“Likes”計數)。

數據通過某種緩存或消息隊列(例如,RabbitMQ,ZeroMQ)排隊,並通過單獨的數據庫批量寫入過程,或者由計算密集型後端服務進行消化,再寫入更好的能夠執行此類任務的平臺。類似的行為可以用其他語言或框架實現,但不能在相同的硬件上實現,以維持相同的高吞吐量。

"

介紹 JavaScript 的日益發展帶來了很多變化,當今的 Web 開發面貌已經變得截然不同。在幾年前是很難想象在服務器上運行 JavaScript 的。

在深入研究Node.js之前,你可能想了解使用跨棧的 JavaScript 有什麼好處,它統一了語言和數據格式(JSON),允許你以最佳的方式重用開發人員資源。將 Node.js 合併到技術棧中是一個關鍵優勢。

Node.js 是一個基於 Chrome 的名為 V8 的 JavaScript 引擎構建的 JavaScript 運行環境。值得注意的是,Node.js 的創建者 Ryan Dahl 的“受到 Gmail 等應用的啟發”,目標是為了開發一個具有實時推送功能的網站。在 Node.js 中,他提供了一個用於處理非阻塞事件驅動的 I/O 工具。

用一句話來概括:Node.js 在基於websockets 推送技術的實時 Web 應用中大放異彩。在過去的 20 多年來我們一直在使用基於無狀態請求 - 響應模式的無狀態 Web 應用,現在終於擁有了能夠實時雙向連接的 Web 應用,其中客戶端和服務器都可以啟動通信,並允許它們自由地交換數據。

這與典型的總是由客戶端發起通信的 Web 響應模式形了成鮮明的對比。此外它也同樣基於在標準端口 80 上運行的開放 Web 技術棧(HTML,CSS和JS)。

有人可能會爭辯說,我們多年來一直以 Flash 和 Java Applet 的形式做到這一點 —— 但實際上,這些只是使用 Web 作為傳輸協議將數據傳給客戶端的沙盒環境。此外,它們是隔離運行的,通常在非標準端口上運行,這可能需要額外的權限。

憑藉其優勢,Node.js 在依賴其獨特優勢的眾多知名公司的技術堆棧中發揮著關鍵作用。 Node.js 基金會幾乎已經整合了所有最好的想法,可以在 Node.js 基金會的案例研究頁面上找到關於為什麼企業應該考慮 Node.js 的簡短PPT。

在本文中,我將不僅要討論如何使用這些優勢,而且還要討論 為什麼 你可能想要使用 Node.js ,並用一些經典的 Web 應用程序模型作為示例。

它是如何工作的?

Node.js 的主要思想是:在面向跨分佈式設備運行的數據密集型的實時程序時,使用非阻塞、事件驅動的 I/O 來保證輕量和高效。

這讀起來很拗口。

這意味著 Node.js 不是 一個即將成為主宰 Web 開發界的能夠解決一切的新平臺。 **相反,它是一個滿足特定需求的平臺。**理解這一點絕對是有必要的。你絕不希望將 Node.js 用於 CPU 密集型的操作;實際上,將它用於進行大量繁重運算的場合將會消除它幾乎所有的優點。 Node.js 真正發揮作用的地方在於構建快速、可擴展的網絡應用,因為它能夠以高吞吐量處理大量兵法連接,這相當於具有高可擴展性。

其底層的工作原理非常有趣。傳統的 Web 服務技術每個連接(請求)都會產生一個新線程,佔用系統內存並最終受限於可用的最大內存,而 Node.js 在單線程上運行,使用非阻塞 I/O 調用,允許它支持數以萬計的併發連接(在 event loop 中維持)。

為什麼要用 Node.js | Node.js Foundation 官方介紹

快速計算:假設每個線程需要 2 MB 內存,那麼在有 8 GB 內存的系統上運行的話,理論上最多有 4000 個併發連接*(計算來自 Michael Abernethy 的文章 “Just what is Node.js?“,2011年在 IBM developerWorks 上發佈;不幸的是,這篇文章的鏈接現在已經失效了)*,這還沒有算上線程之間的上下文切換的成本。這就是你通常在傳統的 Web 服務器技術中處理的場景。通過避免所有這些問題,Node.js 實現了超過 1M 連接併發數的級別,以及 600k 的 websockets 併發連接數。

當然,編寫 Node.js 應用的潛在缺陷是存在客戶端請求之間共享單個線程的問題。首先,繁重的計算可能會阻塞 Node 的單個線程並導致 所有 客戶端出現問題(稍後會詳細說明),因為傳入的請求將被阻塞,直到計算完成為止。其次開發人員需要 非常小心,不要讓異常冒泡到到核心(最頂層)Node.js 事件循環,這將導致 Node.js 實例終止(程序崩潰)。

為了避免異常冒泡到頂層,常用技術是將錯誤作為回調參數傳遞迴調用者(而不是像在其他環境中那樣拋出它們)。即使一些未被處理的異常冒泡到頂層,也有一些工具來監視 Node.js 進程並執行必要的恢復崩潰 (雖然可能無法恢復到用戶會話的當前狀態),最常見的是 Forever 模塊。

npm:node 包管理器

在討論 Node.js 時,一件絕對不應該被忽略的事是支持使用內置的 npm 工具進行包管理,默認情況下每個 Node.js 環境都會安裝。 npm 模塊的概念非常類似於 Ruby Gems:一組可通過在線存儲庫輕鬆安裝,具有版本和依賴關係管理的可重用組件,。

可以在 npm 網站上找到已打包模塊的完整列表,也可以使用自動與 Node.js 一起安裝的 npm CLI 工具進行訪問。模塊生態系統對所有人開放,任何人都可以發佈自己的模塊,發佈的模塊將出現在 npm 存儲庫中。有關 npm 的簡介,請參閱初學者指南,以及 npm 發佈教程中關於發佈模塊的部分。

一些很有用的 npm 模塊是:

  • express —— Express.js,一個受 Sinatra 啟發的 Node.js Web 開發框架,當今大多數 Node.js 應用程序的事實標準。
  • hapi —— 一個模塊化的且非常易於使用的以配置為中心的框架,用於構建 Web 和服務應用
  • connect —— Connect 是 Node.js 的可擴展 HTTP 服務器框架,提供了一系列稱為中間件的高性能“插件”作為Express的基礎。
  • socket.iosockjs —— 今天最常見的兩個 websockets 服務器端組件。
  • pug(以前叫 Jade)—— 受 HAML 啟發的流行模板引擎之一,Express.js 中的默認選項。
  • mongodbmongojs —— MongoDB 包裝器,為 Node.js 中的 MongoDB 對象數據庫提供 API。
  • redis —— Redis 客戶端。
  • forever —— 可能是確保給定 node 腳本連續運行的最常用實用程序。在遇到意外故障時,將 Node.js 的進程保持在生產狀態。
  • bluebird —— 功能齊全的 Promises/A+ 實現,性能非常出色
  • moment —— 用於解析、驗證、操作和格式化日期的輕量級 JavaScript 日期庫。

列表還在不斷增長。那裡有很多有用的包,可供所有人使用。

哪些場合應該使用 Node.js

在線聊天

在線聊天是最典型的實時多用戶應用,也是 Node.js 的最佳案例:它是一個輕量級、高流量、數據密集型(但是低處理和計算)的應用程序,可分佈式跨設備運行。它也是一個很好的學習案例,因為它很簡單,但涵蓋了你在典型的 Node.js 程序中所使用的大部分範例。

讓我們試著描繪它是如何工作的。

假設一個最簡單的場景,在我們的網站上有一個聊天室,人們可以通過一對多(實際上是對所有人)的方式交換消息。

在服務器端,我們有一個簡單的 Express.js 程序,它實現了兩件事:1) 一個GET 請求的處理程序,它提供了包含留言板和用於初始化新消息輸入的“發送”按鈕的功能,以及2) 用於偵聽 websocket 客戶端發出的新消息的w ebsockets 服務器。

在客戶端,我們有一個 HTML 頁面,其中設置了幾個處理程序,一個用於“發送”按鈕的單擊事件,它接收輸入消息並將其發送到 websocket,另一個用於偵聽新的傳入消息並顯示在 websockets 客戶端上(即服務器希望客戶端顯示的其他用戶發送的消息)。

當其中一個客戶發佈消息時,會發生以下情況:

  • 瀏覽器捕獲單擊“發送”按鈕事件處理 JavaScript 程序,從輸入字段(即消息文本)中獲取值,並使用連接到我們服務器的 websocket 客戶端發出 websocket 消息(在網頁初始化時初始化) 。
  • websocket 連接的服務器端組件接收消息,並使用廣播方式將其轉發給所有其他的客戶端。
  • 所有客戶端都通過在網頁中運行的 websockets 客戶端組件接收新消息。然後,他們通過將新消息添加頁面上並更新。
為什麼要用 Node.js | Node.js Foundation 官方介紹

這是最簡單的例子。對於更強大的解決方案,你可以使用基於 Redis 的簡單緩存。或者在更高級的解決方案中,可以用消息隊列作為消息路由,還可以實現更強大的傳遞機制,例如可以在連接丟失或在客戶端脫機時存儲消息。但無論你做出哪些改進,Node.js 仍將按照相同的基本原則運行:對事件做出反應,處理許多併發連接,並保持用戶體驗的流暢性。

對象數據庫頂層的 API

雖然 Node.js 的確很適合開發實時應用,但它也很適合從對象數據庫(例如MongoDB)公開數據。 JSON 存儲的數據允許 Node.js 在對象與存儲數據一致和沒有數據轉換的情況下良好的運行。

例如,如果你正在使用 Rails,那麼你需要從 JSON 轉換為二進制模型,然後通過 HTTP 再將它們轉為 JSON 在 React.js 或 Angular.js 中使用 ,甚至可以用簡單的 jQuery AJAX 進行調用。使用 Node.js,你可以通過 REST API 直接公開你的 JSON 對象來供客戶端使用。此外,在從數據庫讀取或寫入時(如果你使用的是MongoDB),你無需擔心在 JSON 和其他任何內容之間進行轉換的問題。總之在客戶端、服務器和數據庫中使用統一的數據序列化格式,可以避免多次轉換的麻煩。

隊列輸入

如果你收到了大量併發數據,那麼你的數據庫可能會成為瓶頸。如上所述,Node.js 可以輕鬆地自己處理併發連接。但是因為數據庫訪問是一種阻塞操作(在這種情況下),所以我們遇到了麻煩。解決方案是在數據真正寫入數據庫之前先確認客戶端的行為。

通過這種方法,系統可以在高負載下保持其響應性,這在客戶端不需要確認數據成功寫入時尤其有用。典型的例子包括:記錄或寫入用戶跟蹤數據時進行分批處理;以及最終一致性(經常在NoSQL世界中使用)可以接受的不需要立即作出反映的操作(例如更新 Facebook 上的“Likes”計數)。

數據通過某種緩存或消息隊列(例如,RabbitMQ,ZeroMQ)排隊,並通過單獨的數據庫批量寫入過程,或者由計算密集型後端服務進行消化,再寫入更好的能夠執行此類任務的平臺。類似的行為可以用其他語言或框架實現,但不能在相同的硬件上實現,以維持相同的高吞吐量。

為什麼要用 Node.js | Node.js Foundation 官方介紹

簡而言之:使用 Node,你可以將數據庫寫先入到一個地方,稍後再去處理它們,就像它們已經被成功處理一樣。

數據流

在更傳統的Web平臺中,HTTP 請求和響應被看作是孤立事件,實際上他們是流。可以在 Node.js 中使用這個性質來構建一些很酷的功能。例如文件可以被一邊上傳一邊處理,因為數據通過流進入,我們可以實時的去處理它。這可以用於實時音頻\\視頻編碼,以及在不同數據源的之間進行代理(參見下一部分)。

代理

把 Node.js 用作服務器端代理是很容易的,它能夠以非阻塞方式處理大量的併發連接。這對於為代理不同響應時間的多個服務,或從多個源收集數據的場景特別有用。

例如以下場景:當服務器端程序與第三方資源進行通信時,會從不同的來源提取數據,或者將圖像和視頻等資源存儲到第三方雲服務上。

儘管有專用代理服務器,但是如果你沒有基礎的代理架構,或者你需要本地開發環境,那麼 Node 可能會對你有所幫助。

股票交易商的數據界面

讓我們回到應用程序。可以很容易地用實時網絡解決方案取代的另一個例子是股票經紀人的交易軟件,它用於跟蹤股票價格、執行計算、技術分析以及創建圖表。

如果切換到基於 Web 的實時解決方案,經紀人將可以輕鬆切換工作站或工作場所。很快,我們可能會開始在佛羅里達州的海灘上看到它們......

應用監控儀表板

另一個常見的用例,其中 Node-with-web-socket 完全適合:跟蹤網站訪問者並對他們的交互進行實時的可視化。你可以從用戶那裡實時收集統計信息,甚至可以通過在訪問渠道中特定的點來打開通信渠道,並與訪問者進行有針對性的互動,這種方案可以在這裡找到: CANDDi。

想象一下,如果你能夠實時瞭解訪問者所做的事情,你將如何改善你的業務呢?通過使用 Node.js 的實時雙向套接字,現在就可以做到了。

系統監控儀表板

在基礎設施方面,。比如想要為其用戶提供服務監控頁面的SaaS提供商(例如,GitHub狀態頁面)。通過 Node.js 事件循環,我們可以創建一個功能強大的基於 Web 的儀表板,以異步方式檢查服務的狀態,並使用 websockets 將數據推送到客戶端。公司內部和公共服務的狀態都可以使用該技術得到實時報告。

注意:不要嘗試在 Node.js 中構建硬實時系統(即需要一致響應時間的系統)。對於那類應用程序,Erlang 可能是更好的選擇。

哪些場合可以使用 Node.js

服務器端 Web 應用

配合 Express.js 的 Node.js 也可在服務器端創建經典 Web 應用。對於這種方法,有人支持也有人反對。以下是一些需要考慮的問題:

優點:

  • 如果你的程序沒有任何 CPU 密集型計算,可以用 Javascript 和對象存儲數據庫(如MongoDB)構建它,甚至可以在數據庫級別進行構建。這顯著的簡化了開發工作。
  • 爬蟲會收到一個能夠完全呈現的 HTML 響應,這比單頁應用或在 Node.js 上運行的 websockets 應用程序更能進行 SEO 。

缺點:

  • 任何 CPU 密集型計算都會阻止 Node.js 響應,因此線程平臺是一種更好的方法。
  • 將 Node.js 與關係數據庫放一起使用仍然非常困難(更多細節見下文)。如果你要對關係型數據庫進行操作,請並選擇 Rails、Django 或 ASP.Net MVC 等其他環境。

CPU 密集型計算的一種替代方法是創建一個可高度擴展的 MQ 支持環境,該環境具有後端處理功能,以使 Node 成為一個前臺“職員”,並以異步方式處理客戶端請求。

什麼時候不應使用 Node.js

帶有關係型數據庫的服務器端 Web 應用

例如,將 Node.js + Express.js 與 Ruby on Rails 進行比較,當涉及到關係數據訪問時,顯然後者更合適。

與其競爭對手相比,Node.js 的關係型數據庫工具仍然相當原始。另一方面,Rails 提供了開箱即用的數據訪問設置以及數據庫架構遷移支持工具,另外還有其他的 Gems。 Rails 及類似框架擁有成熟的且經過驗證的 Active RecordData Mapper 數據訪問層實現,如果你想要嘗試在純 JavaScript 中複製這些功能的話,那麼祝你好運。

不過,如果你真的傾向於用 JS 實現一切,請查看 Sequelize 和 [Node ORM2](github.com/dresende/no… ORM2)。

如果僅僅是把 Node.js 用作面向公眾的界面,同時用 Rails 後端訪問關係數據庫,這是可以的,而且這種方式並不罕見。

繁重的服務器端計算與處理

當涉及到繁重的計算時,Node.js 並不是最好的平臺。你絕對不想用 Node.js 去構建一個 Fibonacci 計算服務器。通常,任何 CPU 密集型操作都會通過事件驅動的非阻塞 I/O 模型來抵消 Node 提供的所有吞吐量優勢,因為當線程被數字運算佔用時,任何傳入請求都將被阻止。

正如前面所說的,Node.js 是單線程的,只使用一個CPU核心。在多核服務器上添加併發性時,Node 核心團隊以 cluster module 的形式完成一些工作。你也可以很容易地在反向代理 nginx 的後面運行幾個 Node.js 服務器實例。

如果使用群集,你仍然應該將所有繁重的計算放到在更合適的環境下編寫的後臺進程中,並使它們通過像 RabbitMQ 這樣的消息隊列服務器進行通信。

即使你所有的後臺處理最初可能在同一服務器上運行,這種方法也有可能實現非常高的可伸縮性。這些後臺處理服務可以輕鬆地被分發到單獨的工作服務器,而無需對前置 Web 服務器負載進行配置。

當然,你也可以在其他平臺上使用相同的方法,但是使用 Node.js,你可以獲得我們所討論的高 reqs/sec 吞吐量,因為每個請求都是一個非常快速有效的小任務。

結論

我們討論了 Node.js 從理論到實踐,從它的目標和抱負開始,並以其最佳點和陷阱結束。當人們遇到 Node 的問題時,它幾乎總是唄歸結為**阻塞操作是所有邪惡的根源 —— ** 其中 99% 的直接原因是對 Node 的誤用。

請記住:不要用 Node.js 來解決計算擴展問題。它是為了解決 I/O 擴展問題而設計的,它*做得確實很好

所以,如果你的應用不包含 CPU 密集型操作,也不訪問任何阻塞資源的話,可以利用 Node.js 的優勢,享受快速、可擴展的網絡應用。

作者:前端先鋒

鏈接:https://juejin.im/post/5cecdf606fb9a07ed7405ecd

"

相關推薦

推薦中...