NodeJs簡明教程(1)

NodeJs簡明教程將從零開始學習NodeJs相關知識,助力JS開發者構建全棧開發技術棧!

本文是NodeJs簡明教程的第一篇,將介紹NodeJs總體架構以及重點概念。前端

NodeJs到底是什麼

來看一段官方的說法[1]:node

As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications. In the following "hello world" example, many connections can be handled concurrently. Upon each connection the callback is fired, but if there is no work to be done, Node will sleep.

Google翻譯版本:瀏覽器

做爲異步事件驅動的JavaScript運行時,Node旨在構建可伸縮的網絡應用程序。 在下面的「hello world」示例中,能夠同時處理許多鏈接。 在每次鏈接時都會觸發回調,可是若是沒有工做要作,Node將會休眠。

結合上面的介紹,咱們能夠得出一個結論:服務器

NodeJs的本質是一個Javascript運行時。該運行時基於異步事件驅動進行運做。

異步

本文中的異步指異步IO。維基百科對異步IO的定義[2]:網絡

異步IO是計算機操做系統對輸入輸出的一種處理方式:發起IO請求的線程不等IO操做完成,就繼續執行隨後的代碼,IO結果用其餘方式通知發起IO請求的程序。與異步IO相對的是更爲常見的「同步(阻塞)IO」:發起IO請求的線程不從正在調用的IO操做函數返回(即被阻塞),直至IO操做完成。

一言以蔽之就是:多線程

執行IO請求後,調用方不等執行結果就繼續執行下面的代碼,IO操做完成後執行者會告訴調用者「我執行完了」。在NodeJs中通知方式是「回調」。

事件驅動

事件驅動是相對 線程驅動 而言的。線程驅動 下服務器爲每一個請求新建一個線程去處理。
維基百科對事件驅動的定義[3]:架構

事件驅動程序模型下的系統,基本上的架構是預先設計一個事件循環所造成的程序,這個事件循環程序不斷地檢查當前要處理的信息,根據要處理的信息運行一個觸發函數進行必要的處理。其中這個外部信息可能來自一個目錄夾中的文件,可能來自鍵盤或鼠標的動做,或者是一個時間事件。

以NodeJs的HTTP服務器爲例,當調用server.listen函數時,NodeJs就會建立一個事件循環,當有客戶端請求過來時,NodeJs將該請求入隊列進行後續處理,主線程以及輪詢客戶端請求併入隊列,隊列中的請求執行完畢後會經過回調函數的形式通知主線程,如此循環。app

Javascript運行時

Javascript運行時是個比較複雜的概念,本文在介紹 Javascript運行時 以前介紹一下 Javascript引擎異步

Javascript引擎

維基百科的定義[4]:async

JavaScript引擎是一個專門處理JavaScript腳本的虛擬機,通常會附帶在網頁瀏覽器之中。

我的理解:

Javascript引擎主要是對Javascript代碼進行詞法、語法等分析,經過編譯器將代碼編譯成可執行的機器碼讓計算機去執行。

目前業內出名的Javascript引擎非V8莫屬了。

運行時的組成

Javascript能夠運行在瀏覽器,也能夠運行在服務器(NodeJs)中,有些API或者對象只有瀏覽器有(好比DOM,BOM等),而有些API或者對象只有服務器中有(如文件操做,HTTP服務器等)。

Javascript運行時包括了Javascript引擎、特定環境API、事件循環和事件隊列。

NodeJs架構圖

NodeJs由C++語言基於libuv開發,分層設計,Javascript只是其基於V8提供的上層接口,換句話說,若是把上層接口換成其餘語言實現,好比換成PHP實現,那麼PHP就能夠實現異步事件驅動的服務器,運行時名稱就成爲 NODE-PHP

NodeJs架構圖

  • Node standard library NodeJs標準庫,也是直接提供給開發者調用的頂層代碼
  • Node bindings Javascript和libuv在該層進行通訊,基於V8打通語言壁壘
  • V8 執行JS代碼
  • libuv 高性能異步I/O、事件驅動、線程池的庫,也是NodeJs高性能的保證
  • C-ares 提供異步DNS
  • http_parser、OpenSSL、Zlib 提供HTTP解析、openssl加解密、數據壓縮等接口

NodeJs究竟是不是單線程

不是,主線程Javascript線程是單線程,libuv提供線程池,NodeJs不單單是一個Javascript引擎,而是一套運行時,不能將Javascript線程孤立出來。

NodeJs爲何這麼快

  1. 單線程解決了多線程環境下線程切換開銷以及可能的線程同步開銷
  2. 異步+事件驅動保證了NodeJs主線程不會阻塞,會一直接受請求(這也是受人詬病的地方,其餘語言實現的服務器,請求過大會排隊處理,NodeJs會將請求所有入隊,致使內存暴漲)

NodeJs優缺點以及適合的場景

  1. 因爲主線程Javascript線程是單線程,因此主線程不能作CPU密集操做(好比什麼加解密之類的,這種操做只能有Javascript線程運行,會阻塞事件循環),因此NodeJs適合I/O密集場景,好比常見的(TCP/HTTP服務器)
  2. 對於前端開發者來講,幾乎沒有語言門檻
  3. 跨平臺,NodeJs在主流操做系統都有對應的二進制程序
  4. 標準庫強大,第三方庫也不少,下降了造輪子成本
  5. 易於部署,服務器安裝一個NodeJs程序配合NPM包管理器便可運行,不用像PHP那樣還要安裝擴展,配置前端HTTP服務器

結語

歡迎繼續關注本系列文章。

參考文獻

  1. About NodeJs
  2. 異步IO
  3. 事件驅動
  4. Javascript引擎
相關文章
相關標籤/搜索