學習筆記—Node的基本概念


日常的學習筆記,包括 ES6、Promise、Node.js、Webpack、http 原理、Vue全家桶,后續可能還會繼續更新 Typescript、Vue3 和 常見的面試題 等等。


Node的基本概念

什么是Node?

Node.js是一個基於 Chrome V8 引擎的JavaScript運行環境(runtime),Node不是一門語言是讓js運行在后端的運行時,並且不包括javascript全集,因為在服務端中不包含DOM和BOM,Node也提供了一些新的模塊例如http、fs模塊等。Node.js 使用了事件驅動、非阻塞式 I/O 的模型,使其輕量又高效並且Node.js 的包管理器 npm,是全球最大的開源庫生態系統。到此我們已經對node有了簡單的概念。

Node的高並發

Node在處理高並發,I/O密集場景有明顯的性能優勢。

  • 高並發,是指在同一時間並發訪問服務器。
  • I/O密集指的是文件操作、網絡操作、數據庫,相對的有CPU密集,CPU密集指的是邏輯處理運算、壓縮、解壓、加密、解密。

Web主要場景就是接收客戶端的請求讀取靜態資源和渲染界面,所以Node非常適合Web應用的開發。

說到高並發,肯定就會想起多線程。那么多線程和高並發之間的關系和區別又是什么呢?

多線程

首先我們先來了解一下什么是多線程

多線程示意圖

后端語言(包括Java、C++等)存在一個線程池,每發送一次請求,線程池都會分配一個線程給服務器,用來處理請求,以此類推。因為多線程語言的特點是同步請求,所以在多線程發送請求時,可能會存在單個線程阻塞的情況,需要等待當前這個線程的任務處理完畢后,才會釋放線程並放回到線程池,方便下一批任務的使用。當前線程數超過線程池最大可分配數量時,可能就會出現等待的情況。

  • 多線程優點:可以高效高速的處理多個api請求圖片壓縮、大量計算 等...),屬於cpu密集型

  • 多線程缺點不安全性,假設我們有多個線程需要對數據庫同一個資源進行操作(例如對同一個數據進行修改),就會出現數據安全性的問題 [需要對資源進行加鎖操作]。

多線程並非一起做某一件事,靠的是切換上下文(分時),所以多線程會浪費一些資源

關於多線程的具體概念,可以去查閱相關的資料。

高並發

高並發是單線程的一個概念。

  • 高並發優點:不需要開啟多個線程,節省資源
  • 高並發缺點不適合做復雜操作,如果需要做復雜操作,可以開啟子進程。

Node是多線程的,但是其主線程是單線程。所以我們一直都說,Node其實是單線程語言。

同步異步和阻塞非阻塞

  • 同步就是在執行某段代碼時,代碼沒有得到返回之前,其他代碼無法執行,當得到了返回值后可以繼續執行其他代碼。
  • 異步就是在執行某段代碼時,代碼不會立即得到返回結果,可以繼續執行其他代碼,返回值通過回調來獲取。

關於同步阻塞與異步非阻塞,可以參考我之前的文章。

Node中的EventLoop

Node中EventLoop原理

  • 1.我們寫的js代碼會交給v8引擎進行處理。
  • 2.代碼中可能會調用nodeApi,node會交給libuv庫處理
  • 3.libuv通過阻塞i/o和多線程實現了異步io。
  • 4.通過事件驅動的方式,將結果放到事件隊列中,最終交給我們的應用。
    本階段執行已經被 setTimeout() 和 setInterval() 的調度回調函數。
   ┌───────────────────────────┐
┌─>│           timers          │ 
│  └─────────────┬─────────────┘
|   執行延遲到下一個循環迭代的 I/O 回調。
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
|   僅系統內部使用。
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      
|  檢索新的I/O事件;執行與 I/O相關的回調    ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  setImmediate() 回調函數在這里執行。   └───────────────┘
│  ┌─────────────┴─────────────┐      
│  │           check           │
│  └─────────────┬─────────────┘
|  一些關閉的回調函數
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │  
   └───────────────────────────┘

這里每一個階段都對應一個事件隊列,當event loop執行到某個階段時會將當前階段對應的隊列依次執行。當該隊列已用盡或達到回調限制,事件循環將移動到下一階段。

process.nextTick() 從技術上講不是事件循環的一部分。優先級高於微任務

poll階段:

  1. 檢測Poll隊列中是否為空,如果不為空則執行隊列中的任務,直到超時或者全部執行完畢。

  2. 執行完畢后檢測setImmediate隊列是否為空,如果不為空則執行check階段,如果為空則等待時間到達。時間到達后回到timer階段

  3. 等待時間到達是可能會出現新的callback,此時也在當前階段被清空


本篇文章由莫小尚創作,文章中如有任何問題和紕漏,歡迎您的指正與交流。
您也可以關注我的 個人站點博客園掘金,我會在文章產出后同步上傳到這些平台上。
最后感謝您的支持!


免責聲明!

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



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