Nodejs的運行原理-科普篇

 

前言

Nodejs目前處境稍顯尷尬不少語言都已經擁有異步非阻塞的能力阿里的思路是比較合適的可是必需要注意絕對不能讓node作太多的業務邏輯他只適合接收生成好的數據而後或渲染後或直接發送到客戶端html

爲何nodejs 還能夠成爲主流技術哪前端

是由於nodejs 對於大前端來講仍是很是重要的技術!!!若是你理解nodejs 的編程原理很容易就會理解angularjsreactjs vuejs 的設計原理vue

 

NodeJS

Node是一個服務器端JavaScript解釋器用於方便地搭建響應速度快易於擴展的網絡應用。Node使用事件驅動非阻塞I/O 模型而得以輕量和高效很是適合在分佈式設備上運行數據密集型的實時應用
Node是一個可讓JavaScript運行在瀏覽器以外的平臺它實現了諸如文件系統模塊操做系統 API、網絡通訊等Core JavaScript沒有或者不完善的功能歷史上將JavaScript移植到瀏覽器外的計劃不止一個Node.js 是最出色的一個
node

 

V8引擎

V8 JavaScript引擎是Google用於其Chrome瀏覽器的底層JavaScript引擎不多有人考慮JavaScript在客戶機上實際作了些什麼!react

實際上,JavaScript引擎負責解釋並執行代碼。Google使用V8建立了一個用C++編寫的超快解釋器該解釋器擁有另外一個獨特特徵您能夠下載該引擎並將其嵌入任何應用程序。V8 JavaScript引擎並不只限於在一個瀏覽器中運行angularjs

所以,Node實際上會使用Google編寫的V8 JavaScript引擎並將其重建爲可在服務器上使用ajax

 

事件驅動

在咱們使用Java,PHP等語言實現編程的時候咱們面向對象編程是完美的編程設計這使得他們對其餘編程方法不屑一顧殊不知大名鼎鼎Node使用的倒是事件驅動編程的思想那什麼是事件驅動編程
事件驅動編程爲須要處理的事件編寫相應的事件處理程序代碼在事件發生時執行 
爲須要處理的事件編寫相應的事件處理程序要理解事件驅動和程序就須要與非事件驅動的程序進行比較實際上現代的程序大可能是事件驅動的好比多線程的程序確定是事件驅動的早期則存在許多非事件驅動的程序這樣的程序在須要等待某個條件觸發時會不斷地檢查這個條件直到條件知足這是很浪費cpu時間的而事件驅動的程序則有機會釋放cpu從而進入睡眠態注意是有機會固然程序也可自行決定不釋放cpu),當事件觸發時被操做系統喚醒這樣就能更加有效地使用cpu。
來看一張簡單的事件驅動模型(uml):
數據庫

 

事件驅動模型主要包含3個對象事件源事件和事件處理程序編程

  事件源產生事件的地方(html元素)瀏覽器

  事件點擊/鼠標操做/鍵盤操做等等

  事件對象當某個事件發生時可能會產生一個事件對象該時間對象會封裝好該時間的信息傳遞給事件處理程序

  事件處理程序響應用戶事件的代碼 

 

運行原理

當咱們搜索Node.js奪眶而出的關鍵字就是 「單線程異步I/O,事件驅動」,應用程序的請求過程能夠分爲倆個部分:CPU運算和I/O讀寫,CPU計算速度一般遠高於磁盤讀寫速度這就致使CPU運算已經完成可是不得不等待磁盤I/O任務完成以後再繼續接下來的業務
因此I/O纔是應用程序的瓶頸所在I/O密集型業務中假設請求須要100ms來完成其中99ms化在I/O若是須要優化應用程序讓他能同時處理更多的請求咱們會採用多線程同時開啓100、1000個線程來提升咱們請求處理固然這也是一種可觀的方案
可是因爲一個CPU核心在一個時刻只能作一件事情操做系統只能經過將CPU切分爲時間片的方法讓線程能夠較爲均勻的使用CPU資源但操做系統在內核切換線程的同時也要切換線程的上線文當線程數量過多時時間將會被消耗在上下文切換中因此在大併發時多線程結構仍是沒法作到強大的伸縮性
那麼是否能夠另闢蹊徑呢?!咱們先來看看單線程,《深刻淺出Node》一書提到 「單線程的最大好處是不用像多線程編程那樣到處在乎狀態的同步問題這裏沒有死鎖的存在也沒有線程上下文切換所帶來的性能上的開銷」,那麼一個線程一次只能處理一個請求豈不是無稽之談先讓咱們看張圖

Node.js的單線程並非真正的單線程只是開啓了單個線程進行業務處理(cpu的運算),同時開啓了其餘線程專門處理I/O。當一個指令到達主線程主線程發現有I/O以後直接把這個事件傳給I/O線程不會等待I/O結束後再去處理下面的業務而是拿到一個狀態後當即往下走這就是單線程」、「異步I/O」。
I/O操做完以後呢?Node.jsI/O 處理完以後會有一個回調事件這個事件會放在一個事件處理隊列裏頭在進程啓動時node會建立一個相似於While(true)的循環它的每一次輪詢都會去查看是否有事件須要處理是否有事件關聯的回調函數須要處理若是有就處理而後加入下一個輪詢若是沒有就退出進程這就是所謂的事件驅動」。這也從Node的角度解釋了什麼是事件驅動」。
node.js事件主要來源於網絡請求文件I/O根據事件的不一樣對觀察者進行了分類有文件I/O觀察者網絡I/O觀察者事件驅動是一個典型的生產者/消費者模型請求到達觀察者那裏事件循環從觀察者進行消費主線程就能夠快馬加鞭的只關注業務不用再去進行I/O等待

 

優勢

Node 公開宣稱的目標是 「旨在提供一種簡單的構建可伸縮網絡程序的方法」。咱們來看一個簡單的例子 Java PHP 這類語言中每一個鏈接都會生成一個新線程每一個新線程可能須要 2 MB 的配套內存在一個擁有 8 GB RAM 的系統上理論上最大的併發鏈接數量是 4,000 個用戶隨着您的客戶羣的增加若是但願您的 Web 應用程序支持更多用戶那麼您必須添加更多服務器因此在傳統的後臺開發中整個 Web 應用程序架構包括流量處理器速度和內存速度中的瓶頸是服務器可以處理的併發鏈接的最大數量這個不一樣的架構承載的併發數量是不一致的
Node的出現就是爲了解決這個問題更改鏈接到服務器的方式Node 聲稱它不容許使用鎖它不會直接阻塞 I/O 調用。Node在每一個鏈接發射一個在 Node 引擎的進程中運行的事件而不是爲每一個鏈接生成一個新的 OS 線程併爲其分配一些配套內存)。

 

缺點

如上所述,nodejs的機制是單線程這個線程裏面有一個事件循環機制處理全部的請求在事件處理過程當中它會智能地將一些涉及到IO、網絡通訊等耗時比較長的操做交由worker threads去執行執行完了再回調這就是所謂的異步IO非阻塞吧可是那些非IO操做只用CPU計算的操做它就本身扛了好比算什麼斐波那契數列之類它是單線程這些本身扛的任務要一個接着一個地完成前面那個沒完成後面的只能乾等所以CPU要求比較高的CPU密集型任務多的話就有可能會形成號稱高性能適合高併發的node.js服務器反應緩慢

 

適合場景

一、RESTful API

這是適合 Node 的理想狀況,由於您能夠構建它來處理數萬條鏈接。它仍然不須要大量邏輯;它本質上只是從某個數據庫中查找一些值並將它們組成一個響應。因爲響應是少許文本,入站請求也是少許的文本,所以流量不高,一臺機器甚至也能夠處理最繁忙的公司的 API 需求。

二、實時程序

好比聊天服務

聊天應用程序是最能體現 Node.js 優勢的例子:輕量級、高流量而且能良好的應對跨平臺設備上運行密集型數據(雖然計算能力低)。同時,聊天也是一個很是值得學習的用例,由於它很簡單,而且涵蓋了目前爲止一個典型的 Node.js 會用到的大部分解決方案。

三、單頁APP

ajax不少。如今單頁的機制彷佛很流行,好比phonegap作出來的APP,一個頁面包打天下的例子比比皆是。

總而言之,NodeJS適合運用在高併發、I/O密集、少許業務邏輯的場景

相關文章
相關標籤/搜索