Nodejs目前處境稍顯尷尬,不少語言都已經擁有異步非阻塞的能力。阿里的思路是比較合適的,可是必需要注意,絕對不能讓node作太多的業務邏輯,他只適合接收生成好的數據,而後或渲染後,或直接發送到客戶端。html
爲何nodejs 還能夠成爲主流技術哪?前端
是由於nodejs 對於大前端來講仍是很是重要的技術!!!若是你理解nodejs 的編程原理,很容易就會理解angularjs,reactjs 和vuejs 的設計原理。vue
Node是一個服務器端JavaScript解釋器,用於方便地搭建響應速度快、易於擴展的網絡應用。Node使用事件驅動,非阻塞I/O 模型而得以輕量和高效,很是適合在分佈式設備上運行數據密集型的實時應用。
Node是一個可讓JavaScript運行在瀏覽器以外的平臺。它實現了諸如文件系統、模塊、包、操做系統 API、網絡通訊等Core JavaScript沒有或者不完善的功能。歷史上將JavaScript移植到瀏覽器外的計劃不止一個,但Node.js 是最出色的一個。node
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.js的I/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密集、少許業務邏輯的場景