Node.js應該是當今最火熱的技術之一。本文主要介紹Node.js的特點及應用場景。
Node.js是一個基於Chrome JavaScript運行時建立的一個平台,用來方便地搭建快速的 易於擴展的網絡應用。Node.js借助事件驅動,非阻塞I/O模型變得輕量和高效,非常適合 運行在分布式設備的數據密集型實時應用。
1. 特點
1.1 異步I/O
所謂的異步I/O,是相對同步I/O而言的。程序執行過程中必然要進行很多I/O操作,如讀寫文件、輸入輸出、請求響應等等。通常來說,I/O操作是非常費時的。例如在傳統的編程模式中,你要讀一個幾G的文件,整個線程都暫停下來,等待文件讀完後繼續執行。換言之,I/O操作阻塞了代碼的執行,極大地降低了程序的效率。
關於異步I/O,其實對於前端工程師來說並不陌生,因為發起Ajax請求就是最常見的一種“異步”調用。在Node中,以讀取文件(讀文件是一種耗時的I/O操作)為例,它與發起Ajax請求的寫法很像:
代碼如下:
var fs = require('fs');
fs.readFile('/path', function(err, file) {
console.log('讀取文件完成');
});
console.log('開始讀取文件');
上述代碼在調用fs.readFile後,後續代碼是被立即執行的,“讀取文件完成”的時刻是無法預知的。當線程遇到I/O操作時不會以阻塞的方式等待I/O操作結束,而只是將I/O請求發送給操作系統,繼續執行後續語句。當操作系統完成I/O操作時以事件的形式通知執行I/O操作的線程,線程會在特定時間處理這個事件。
1.2 事件循環與回調函數
所謂事件循環是指Node會把所有的異步操作使用事件機制解決,有個線程在不斷地循環檢測事件隊列。事件循環會檢查事件隊列中有沒有未處理的事件,直到程序結束。事件的編程方式具有輕量級、松耦合、只關注事務點等優勢,但是在多個異步任務的場景下,事件與事件之間各自獨立,如何協作是一個問題。在Javascript中,回調函數無處不在,回調函數是最好的接受異步調用返回數據的方式。
1.3 單線程
Node保持了JS在浏覽器中單線程的特點。單線程的最大好處是不用像多線程編程那樣出處在意狀態的同步問題,沒有死鎖的存在,也沒有線程上下文切換的開銷。單線程也有其弱點,主要表現在三方面:無法利用多核CPU;錯誤會引起整個應用退出,應用的健壯性值得考研;大量計算會占用CPU導致無法繼續調用異步I/O。
為了解決上述問題,Node采用了與HTML5 Web Workers相同的思路,使用child_process來解決但單線程中大計算量的問題。通過將計算分發到各個子進程,可以將大量計算分解掉,然後再通過進程之間的事件消息來傳遞結果。
1.4 跨平台
Node是跨平台的,即同樣的一套JS代碼都可以部署運行在Windows、Linux、OSX等平台。這主要得益於Node在操作系統與Node上層模塊系統之間構建了一層平台層架構libuv。
2. 應用場景
1)、實時應用:如在線聊天,實時通知推送等等(如socket.io)
2)、分布式應用:通過高效的並行I/O使用已有的數據
3)、工具類應用:海量的工具,小到前端壓縮部署(如grunt),大到桌面圖形界面應用程序
4)、游戲類應用:游戲領域對實時和並發有很高的要求(如網易的pomelo框架)
5)、利用穩定接口提升Web渲染能力
6)、前後端編程語言環境統一:前端開發人員可以非常快速地切入到服務器端的開發(如著名的純Javascript全棧式MEAN架構)