Node.js 底層


 

 

 

這次讀了一些關於底層實現的東西:
  1. 《深淺》第3章 異步I/O - node.js是如何實現異步i/o的
  2. Udemy 《Learn and Understand NodeJS Learn and Understand NodeJS》 Section 2&3

V8引擎

首先,學習node.js一定要了解V8引擎,他是一個可以把js直接編譯成(處理器可以識別的)機器碼的東西。

再詳細點,V8是一個
  1. 開源的
  2. 用C++寫的
  3. 根據ECMA標准實現JavaScript
  4. 可以把JavaScript編譯成處理器可以識別的機器碼
  5. 可以獨立運行
  6. 也可以嵌入其他C++應用
的JavaScript引擎。
 

Node.js與V8引擎

普通青年使用V8:運行V8, JavaScript -> V8 —compile—> Machine Code
文藝青年則有這樣一個大膽的想法:
那些普通的js方法太沒意思了,能力優先。如果我可以寫一些C++代碼,當做Add-on加到V8上,這樣V8就有能力識別具有更多的Javascript命令了,就更強大了。比如說file相關的東西,本來js不能做,現在我用c++在底部實現好,然后告訴V8,當用戶在js中寫道file.open(xxx)的時候,就來用c++執行file open的功能,這樣你的js(二b)就是有處理文件能力的js(牛b)了。
 
文藝青年的想法其實就是我們的Node.js:一個把V8引擎嵌進去的C++應用,這個C++應用實現了超級多的customized新功能,這些功能使得這個應用(Node.js)非常的適合服務器開發。
 
服務器開發都需要什么新功能呢 === Node.js實現的新功能都包括哪些方面呢:
  1. 管理可復用代碼
  2. 處理文件
  3. 處理數據庫
  4. 互聯網通信
  5. 接受request,發送respond
  6. 處理需要一定時間才能完成的工作

 

Node.js架構

  1. 第一層是C++ core,就是那些新加的customized功能 (其他講解中,還會提到比如event loop,libuv等,這些之后說)。
  2. 第二層是JS core,這一層用js實現,基於/調用C++ core,讓用戶可以更好的使用那些C++功能,同時也實現了許多常用的功能。
在node.js源碼中,C++ core是在src文件夾內。JS core是在lib文件夾內。由此可見二者的層級關系。
 

Node.js 異步I/O

Node.js如何實現異步 I/O, 從JS到OS到底發生了哪些步驟(這個是udemy+《深淺》的合體版總結)

  1. 你寫的js代碼調用了node.js的JS core (比如 fs相關功能:github.com/nodejs/node…),並且你設定了一個回調函數
  2. JS core部分調用了C++ core (fs.js 調用的其中一個.cc: github.com/nodejs/node…)
  3. C++ core調用libuv
  4. C++ core調用libuv的方法來封裝請求對象(異步I/O過程中重要的中間產物,中間指的是從js到os之間),其中包含了異步I/O中最重要的東西之一:回調函數。
  5. libuv把封裝好的請求對象發到OS
  6. 發到OS中的線程池(thread pool)等待被執行
  7. 線程池中某一線程將發來的請求對象中包含的I/O操作進行執行,結果存在該請求對象的req->result屬性中。然后提交完成狀態,也就是類似通知說"我完成了!”,之后把線程歸還給線程池
  8. 處於完成狀態的請求對象,被觀察者(圖中的兩個小人兒,不同類型的事件有不同的觀察者)在事件循環(Event Loop:大while循環,每個循環叫一個tick)中提出來(通過libuv中方法來檢查是否有執行完的請求),然后放到隊列(Completed Events Queue)中
  9. 事件循環從觀察者的隊列中取出處於完成狀態請求對象
  10. 取出其中包含的I/O操作執行結果以及回調函數,發到V8中執行。到這就達到了調用#1中設定的回調函數的目的。
a. V8引擎執行的JavaScript是同步的(sync)( stackoverflow.com/questions/2…)且單線程
b. #1-#9 與 #10 是同時在工作的,I/O事件一個一個執行,然后最后發送到V8引擎中一個一個(因為JS是同步的)的執行回調函數
c. 由於b,整個Node.js有了異步I/O的能力
d. 事件驅動(event driven)、非阻塞(non-blocking)I/O的特點也就可以解釋了。事件驅動就是指的#7-#10,事件被完成觸發了之后各個步驟,直到最后執行回調函數。非阻塞I/O就是整個#1-#10這個過程,我們在V8中執行的JavaScript代碼並不會因為事件的執行而停止,#1-#9和#10同時工作,一個執行I/O事件,一個得到通知執行回調函數。
e. 從d的解釋中,可以更好的理解上一篇文章中最后那段說Node.js是單線程/多線程。
 
下次寫事件(Event)和事件發射器(Event Emitter)相關的東西。歡迎大家交流,指正~

作者:macctown
鏈接:https://juejin.im/post/5a24cfe7f265da431e16977a
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM