node項目架構與優化

爲何要用node

一、先後端耦合太緊密,中間加一層node,還要給前端裝一些亂七八糟的東西  java啥的服務環境。還有後臺返回接口的時候無論前端需不須要那些接口一塊兒返回,其實只用到1~2 條數據。原本ajax就很是消耗時的事,就用其中一條,用node作一層中間層處理把沒用的接口剔除掉。javascript

二、好比:一個10天項目,後臺開發6天,前臺2天,測試2天。後臺開發時,沒有接口,前端得等着後臺的接口,若是後臺某種狀況推遲了一天,前端就1天開發,測試要2天,確定前端開發不完。使用node咱們能夠並行開發,提升開發效率。前端

三、proxy 代理層    java->node    前端->node  這種狀況叫BFF,後臺是沒有跨域的。作了一層中間代理,能夠本身控制路由,前端請求發給node,就不會出現跨域的問題。node socket io 實時通信。java

四、node容錯,性能難作。node

node異步IO原理淺析及優化方案

  • 異步IO的是與非

    前端經過異步IO能夠消除UI阻塞。
    假設請求資源A的時間爲M,請求資源B的時間爲N,那麼同步的請求耗時就爲M+N,若是採用異步的方式佔用時間爲MAX(M,N)。
    隨着業務的複雜,會引入分佈式系統,時間會線性的增長M+N+...和MAX(M,N,...),這會放大同步和異步之間的差別。
    I/O是昂貴的,分佈式I/O是更昂貴的。

    一些底層知識linux

    一、nginx

      CPU是鍾週期:1/CPU主頻->1s/3.1GHzweb

      一級CPU是鍾週期:3.5GHz   1/3.5*3  io時間ajax

    二、算法

    p是並行系統鐘的處理器數量;編程

    f=ws/w爲串行部分的比例;

     咱們分佈到其餘機器裏,每一個機器都用一樣的代碼。網絡要請求這文件,就比較慢 整個時間就比較長。

     並非全部的全部並行的好,也並很多全部串行就好,分狀況。系統會自動根據狀況來判斷使用並行仍是串行。

    三、操做系統對計算機進行來抽象,將全部輸入輸出設備抽象爲文件。內核在進行文件I/O操做時,經過文件描述符進行管理。應用程序若是須要進行I/O須要打開文件描述符,在進行文件和數據的讀寫。異步IO不帶數據直接返回,要獲取數據還須要經過文件描述符再次讀取。

   

 

    

    NodeJS使用與IO密集型不適用於CPU密集型

    好比銀行,每次計算價格,java是多線程能夠處理多個任務,而Nodejs是單線程用異步不停的寫,寫發上也很是複雜。能夠有框架處理單線程問題,可是性能上仍是不如java。

  • Node對異步IO實現

  完美的異步IO應該是應用程序發起阻塞調用,無需經過便利或者事件幻想等方式輪詢。

前端的event loop跟node event loop不同,前端比node event loop還要複雜一些。node程序進來不停的轉,就等於咱們把米放到電飯煲裏,定好時間,咱們去忙別的,等他作好以後,會提示,已經作好了。

  • 幾個特殊對API

    一、setTimeout和setInterval線程池不參與

    二、process.nextTick()實現相似setTimeout(function(){},0);每次調用放入隊列中,在下一輪循環中取出。

    三、setImmediate();比provess.nextTick()優先級低

    四、Node如何實現一個Sleep?

    

async function test(){
  console.log('hello');
  await seelp(1000);
  console.log('word');         
}
function seelp(time){
  return new Promise(resolve=>setTimeout(resolve,time))
}
test()

 

  • 函數式編程在Node中對應用

    一、高階函數:能夠將函數做爲輸入或者返回值,造成一種後續傳遞風格的結果接受方式,而非單一的返回值造成。後續傳遞風格的程序將函數業務重點從返回值傳遞到回調函數中。

app.use(function(){
   //todo 
})
var emitter = new event.eventEmitter;
emitter.on(function(){
    //todo
})

    二、偏函數:指定部分參數產生一個新的定製函數的形式就是偏函數。node中異步編程很是常見,咱們經過哨兵變量會很容易形成業務的混亂。underscore,after變量。

  • 經常使用的Node控制異步API的技術手段

    一、step、wind(提供等待的異步庫)、bigpipe、Q.js

    二、Async、Await

    三、Promise/Defferred是一種先執行異步調用,延遲傳遞的處理方式。Promise是高級接口,事件是低級接口。低級接口能夠構建更多複雜的場景,高級接口一旦定義,不太容易變化,再也不有低級接口的靈活性,但對於解決問題很是有效。

    四、因爲Node基於V8的緣由,目前還不支持協程。協程不是進程或線程,其執行過程更相似於子例程,或者說不帶返回值的函數調用。

    一個程序能夠包含多個協程,能夠對比一個進程包含多個線程。來比較協程和線程。咱們知道多個線程相對獨立,有本身的上下文,切換受系統控制;而協程也相對獨立,有本身的上下文,可是其切換由本身控制,由當前協程切換到其餘協程有當前協程來控制。

內存管理與優化

   V8垃圾回收機制

    node使用javascript在服務端操做大內存對象受到了必定的限制,64位系統下約爲1.4GB,32位系統是0.7GB

    process.memoryUsage->rss、heaptTotal、heapUsed

    V8的垃圾回收策略主要基於分代式垃圾回收機制。在自動垃圾回收的演變過程當中,人們發現沒有一種垃圾回收算法可以勝任全部場景。V8內存分爲新生代和老生代。新生代爲存活時間較短對象,老聖代爲存活時間較長的對象。

   Scavenge算法

    在分帶基礎上,新生代的對象主要經過Scavenge算法進行垃圾回收,在具體實現時主要採用cheney算法,cheney算法是一種採用複製的方法實現的垃圾回收算法。它將內存一分爲二,每個空間稱爲semispace。這兩個semispace中一個處於使用,一個處於閒置。處於使用的稱之爲From,檢查From存活對象複製到To。非存活被釋放。而後互換位置。再次進行回收,發現被回收過直接晉升,或者發現To空間已經使用來超過25%。他的缺點只能使用堆內存的一半,這是一個典型的空間換時間的辦法,可是新生代生命週期較短,偏偏就適合這個算法。

  

  老生代空間生成完成確定要有東西管理它,就有來mark-sweep和mark-compact

    V8老生代主要採用mark-sweep和mark-compact,在使用Scavenge不合適。一個是對象較多須要賦值量太大並且仍是沒能解決空間問題。Mark-Sweep是標記清除,標記那些死亡的對象,而後清除。可是清除事後出現內存不連續的狀況,全部咱們要使用Mark-Compact,他是基於mark-sweep演變而來的,它現將活着的對象移到一邊,移動完成後,直接清理邊界外的內存。當CPU空間不足的時候會很是高效。V8還引入來延遲處理,增量處理,並計劃引入並標記處理。

  

  常見的內存泄漏問題

  一、無限制增加的數組

  二、無限制設置屬性和值

  三、任何模塊內的私有變量和方法均是永駐內存的a=null

  四、大循環,無GC(垃圾回收機制)機會

  內存泄漏分析

  node-inspector

  console.log("Server PID",process.pid);

  sodu node --inspect app.js

  whie true;do curl "http:localhost:1337/";done

  top -pid 2322

大規模Node站點結構原理分析

  經典的MVC框架

  model-view-Controller

javaweb多層架構

node 集羣應用

   預備上線

  一、前端工程化的搭載動態文件的MAP分析壓縮打包合併至CDN

  二、單側、壓力測試、性能分析工具發現Bug

  三、編寫nginx-conf實現負載均衡和反向代理

  四、PM2啓動應用生序小流量灰度上線,修復Bug

  五、上線前的不眠夜、你見過凌晨5點的北京麼?

  多線程

  一、master進程均爲主進程,Fork能夠創造主進程。

  二、經過child_process能夠和NET模塊組合,能夠建立多個線程並監聽統一端口。經過句柄傳遞完成自動啓動、發射自殺信號、限量重啓、負載均衡。

  三、node默認的機制是採用操做系統的搶佔式策略。閒着的進程爭搶任務,可是會形成CPU閒置的IO暫時並未閒置。Node後來引入來Round-Robin機制,也叫輪詢調度。主進程接受任務,在發。

  四、每一個子進程作好本身的事,而後經過進程間通訊來將他們連接起來。這符合Unix的設計理念,每一個進程只作一件事,並作好。將福啊分解爲簡單,將簡單組合程強大。

  PM2

  pm2是一個自帶負載均衡功能的node應用的進程管理器。

  當你要把你的獨立代碼利用所有的服務器上的全部CPU,並保證進程永遠活着,0秒重載。

  一、內建負載均衡(使用node cluster集羣模塊)

  二、後臺運行

  三、0秒停機重仔

  四、具備Ubuntu和CentOS的啓動腳本

  五、中止不穩定的進程(避免無限循環)

  六、控制檯檢測

  七、提供HTTP API

  八、遠程控制和實時的接口API(Nodejs 模塊,容許和PM2進程管理交互)

    測試過Nodejs v0.11 v0.10 v0.8版本,兼容CoffeeScript,基於linux和MacOs

  

我以前是前端連java感受還能夠,若是我中間加一層node,是否是就變慢了呢,並非,首先java跟node在一樣一個機房他倆請求的時間被嚴格限制在1ms(毫秒),甚至一些團隊100ms已經頂天了,300ms服務確定有問題。用戶確定沒法感知的,node和java走了一次http,會有3次握手,即便是毫秒也是一次浪費,node和java 走的是Linux Virtual Server(Linux虛擬服務器)通訊。

相關文章
相關標籤/搜索