創始者認爲 web 服務器有兩個要點,事件驅動和非阻塞 I/O。前端
最初創始者想將其命名爲 web.js 也就是一個 web 服務器,可是項目的發展超過了他最初單純開發一個 web 服務器的想法,變成了構建網絡應用的基礎框架。node
V8 給 Chrome 瀏覽器帶來了強勁的心臟,也成爲了 JavaScript 稱爲 node 語言的很大權重值。web
Chrome 瀏覽器和 Node 組件構成 區別以下圖: 瀏覽器中,除了 v8 引擎還有一個 webkit 佈局引擎,HTML5 使得瀏覽器開放了不少功能給前端的 HTML 及 JavaScript,可是HTML5 的統一卻相對緩慢,JavaScript 做爲一個圖靈完備的語言,受限於瀏覽器中間層提供的支持。 除了 HTML 、webkit 和 顯卡這些UI 相關的技術沒有支持外,Node 結構與 Chrome 十分相近。 它們都是基於事件驅動的一步架構,瀏覽器經過事件驅動來服務界面上的交互,Node 經過事件驅動來服務 I/O。 Node 中,JavaScript 能夠爲所欲爲的訪問本地文件,搭建 websocket 服務端,能夠鏈接數據庫,可使用多進程。 JavaScript 再也不限制於瀏覽器與 CSS 樣式表、DOM 樹。 Node 不處理 UI,但用瀏覽器相同的機制和原理運行。 打破了 JavaScript 只能在瀏覽器中運行的局面,下降了先後端轉換所須要的上下文交換代價。數據庫
前端經常使用到的就是經過 AJAX 請求數據,發送和收到之間有一個時間的間隔,在收到數據後後續代碼當即執行,可是收到的時間確是不肯定的,這是一種只注重結果,不注重過程的表現。以下圖所示。 在 Node 中異步 I/O 也很常見,能夠用讀取文件爲例:編程
const fs = require('fs');
fs.readFile('../Desktop/IMG_3648.jpeg', (err, file) => {
console.log(file);
console.log('文件讀取完成');
});
console.log('發起讀文件的流程!');
複製代碼
代碼中示例「發起讀取文件的流程」先於「文件讀取完成」執行,什麼時候完成基於覈實徹底讀取內容,執行流程以下圖: 在 Node 中,咱們能夠從語言層面很天然的進行並行的 I/O 操做,每一個調用之間無需等待以前的 I/O 調用完成,讀取兩個 文件的最慢速度取決於讀取最慢的那個文件的耗時。對於同步 I/O 則是兩個文件的綜合。windows
事件的編程方式具備輕量級、鬆耦合、只關注實物點等優點,可是在多個異步任務的場景下,事件與事件之間各自獨立,如何協做是一個問題。 函數做爲JavaScript 的第一等公民,將函數做爲對象傳遞給方法做爲實參進行調用。回調函數是最好的接受異步調用返回數據的方式。後端
Node 保持了JavaScript 單線程的特色,單線程最大的好處就是無需像多線程同樣到處在乎狀態同步的問題,沒有死鎖存在,也沒有線程上下文交換帶來的性能開銷。 單線程的弱點:瀏覽器
爲解決這些問題,Google 開發了 Gears, HTML5 標準增長了 web workers 標準,Google 放棄了 Gears 支持 web workers。 Web workers 可建立線程進行計算,已解決 JavaScript 大計算阻塞 UI 渲染的問題。 Node 採用了與 web workers 相同的思路解決單線程中大量計算的問題: child_process。服務器
最初的 node 只可在 Linux 上使用,後續增長了 windows 平臺的支持。websocket
I/O 密集型的優點主要在於 Node 利用時間循環的處理能力,而不是啓動每個線程爲每個請求服務,資源佔用極少,因此 Node 面向網絡並擅長並行 I/O。
CPU 密集型業務在Node 上的支持並不可怕,可是會帶來的挑戰是:JavaScript 做爲單線程的語言,CPU 密集型業務會佔用長時間的線程進行計算,致使 CPU 時間片沒法釋放,使得後續的 I/O 沒法發起,可是適當調整和分解大型運算任務爲多個小任務,使得運算能夠及時釋放,不阻塞 I/O 調用的發起,這樣既能夠享受到異步 I/O 的好處,也能充分利用 CPU。
若是是純 CPU 的業務,能夠經過兩種方式進行充分利用 CPU
Node 能夠經過將舊有的接口做爲數據源,發揮並行優點,不關心背後用什麼語言實現。
Node 高效利用 I/O 的過程也是高效使用數據庫的過程,對於 Node 而言,使用數據庫這種行爲只是一次普通的 I/O。對數據庫而言倒是一次複雜的計算,也是充分壓榨硬件資源的過程。