簡(jiǎn)介
Node.js 專注于實(shí)現(xiàn) web 高性能的服務(wù)器,是一個(gè)讓 JavaScript 運(yùn)行在服務(wù)器上的平臺(tái)。他使用 Chrome 瀏覽器的 V8 引擎作為 JS 代碼的解釋工具,底層使用 C++ 進(jìn)行開發(fā),而 V8 引擎也正是基于 C++ 開發(fā)的。
Node.js 并不是一種新的語言,他是基于 JavaScript 實(shí)現(xiàn)的,但是他讓 JavaScript 煥發(fā)出了新的活力,將 JavaScript 的觸角伸到了服務(wù)器端。
Node.js 和傳統(tǒng)的服務(wù)器端程序的最大區(qū)別在于 Node.js 沒有 Web 容器的概念。一般來服務(wù)器程序比如 PHP、JSP、Python、Perl、Ruby 等都需要運(yùn)行在 Web 容器中才能被訪問,最常用的 Web 容器比如說 Apache、Nginx 等。但是 Node.js 沒有!通過對(duì)于頂層路由的設(shè)計(jì)能夠制定出很簡(jiǎn)潔清晰的 URL。
特點(diǎn)一:?jiǎn)尉€程
Node.js 的另一大特點(diǎn)在于他是單線程的,整個(gè) Node.js 程序運(yùn)行在單一的一個(gè)線程上。
一個(gè) Java Web 項(xiàng)目,用戶發(fā)起請(qǐng)求會(huì)為其創(chuàng)建一個(gè)線程,而每一線程都需要占用一定的內(nèi)存,所有對(duì)于服務(wù)器的要求會(huì)隨著用戶數(shù)的增加而增加,硬件成本也相應(yīng)提高。同時(shí)使用多線程會(huì)存在上下文切換和線程銷毀的開銷,如果使用單線程就能避免這些應(yīng)為多線程帶來的系統(tǒng)開銷,提高系統(tǒng)運(yùn)行效率。
Node.js 不會(huì)為每個(gè)用戶創(chuàng)建一個(gè)新的線程,而是使用同一個(gè)線程接收所有的請(qǐng)求。使用一個(gè)線程在面對(duì)多個(gè)用戶請(qǐng)求時(shí),Node 不能像多線程那樣并行地對(duì)其進(jìn)行處理。在單線程上我們順次執(zhí)行程序,在一個(gè)請(qǐng)求沒有執(zhí)行完的時(shí)候,線程就會(huì)阻塞,下一個(gè)請(qǐng)求就無法進(jìn)行。
特點(diǎn)二:非阻塞式 IO
為了應(yīng)付單線程的阻塞問題,Node 使用了非阻塞 I/O 機(jī)制。
處理一個(gè)請(qǐng)求時(shí)最耗時(shí)的操作是各種 I/O 操作,最頻繁的就是對(duì)數(shù)據(jù)庫的讀寫操作,或者是對(duì)文件的讀寫操作。在單線程中如果執(zhí)行到 I/O 操作,則線程會(huì)在此阻塞等待返回結(jié)果。
Node 為了應(yīng)付費(fèi)時(shí)的 I/O 操作使用了非阻塞 I/O 模式。當(dāng)程序一旦執(zhí)行到了 I/O 操作的部分,則立即將 I/O 操作交給回調(diào)函數(shù),自己則繼續(xù)執(zhí)行后面的程序。
這里就有兩點(diǎn)需要注意的。
一是執(zhí)行回調(diào)函數(shù)之后的代碼不能依賴回調(diào)函數(shù)的結(jié)果。比如用戶登錄的操作,需要查詢數(shù)據(jù)庫驗(yàn)進(jìn)行校驗(yàn),之后的登錄操作需要依賴回調(diào)的結(jié)果,此時(shí)必須等待返回校驗(yàn)結(jié)果才能進(jìn)行登錄操作。
二是執(zhí)行回調(diào)函數(shù)之后何時(shí)再繼續(xù)執(zhí)行。所以必須要有事件循環(huán),回過頭來繼續(xù)執(zhí)行操作,就需要不斷檢查線程上有沒有沒有處理完的事件,排隊(duì)實(shí)現(xiàn)他們。
因此 Node 的這條線程一直處于運(yùn)行狀態(tài)不會(huì)阻塞,CPU 的利用率一直很高。
特點(diǎn)三:事件驅(qū)動(dòng)
Node 的第三個(gè)特點(diǎn)就是事件驅(qū)動(dòng)。也就是前面講的在線程執(zhí)行 A 操作的過程中采用回調(diào)函數(shù)的形式轉(zhuǎn)而處理 B 事件,在 B 事件處理完之后再去執(zhí)行 B,如網(wǎng)上一張圖片所示:

事件在循環(huán)執(zhí)行之中,當(dāng)遇到 I/O 操作則采用回調(diào)函數(shù)處理,處理完的事件則會(huì)排隊(duì)等候再次執(zhí)行,形成了一個(gè)個(gè)的事件環(huán)。
Node 通過非阻塞 I/O 的機(jī)制和事件驅(qū)動(dòng)的方式讓單線程的程序?qū)崿F(xiàn)了多線程的效果。讓一個(gè)線程永遠(yuǎn)處于忙碌的狀態(tài),不會(huì)造成資源的浪費(fèi)。這樣就能降低硬件的成本卻不會(huì)影響程序執(zhí)行的效率。