大規模NodeJS項目架構與優化

聊聊大規模NodeJS項目架構

  • NodeJS異步IO原理淺析及優化方案
  • NodeJS內存管理機制及內存優化
  • 大規模Node站點結構原理分析
  • 服務器集群管理與Node集群的應用

異步IO原理淺析


  1. 異步IO的是與非
  2. Node對異步IO的實現
  3. 幾個特殊的API
  4. 函數式編程在Node中的應用
  5. 常用的Node控制異步API的技術手段

異步IO的好處

  • 首先,前端通過異步IO可以消除UI阻塞。
  • 然后,如果是請求資源,請求A資源時間為M,請求B資源時間為N,如果是同步就需要M+N,如果是異步就需要MAX(M,N)。
  • 隨著業務不斷擴大,引入分布式系統(一個業務拆分成多個小業務),時間會呈線性增加,同異步之間的差異會更加明顯。
    IO是非常昂貴的,分布式IO更是昂貴的。
  • NodeJS是適用于IO密集型,不適用于CPU密集型。為什么說node使用與IO密集型呢,因為IO密集型是異步的這樣的機制。有進有出就是IO。一下子進來500W請求,我交給異步去處理,處理完再通知我。
  • JAVA和PHP也有異步,但是node天然就是異步,所以node更適用于游戲實時的這種,主播平臺,都用node,還有就是傳統代理,用node去處理,前端接收請求就少一點,阿里美團都會有中間層做處理。
  • 底層知識:CPU時鐘周期,一個CPU時鐘周期(1s/2.8hz)Ghz;異步好,但并非所有的異步都好,阿姆達爾定律可以計算出通過改進計算機某一部分獲得的性能增益。Amdahl’s law 【1】【2】(Ws串行數);文件操作符,內核在進行文件IO操作時,通過文件操作符進行管理。node在o的那一個等待事件輪詢把文件操作符返回給你。
  • 寫完以后去壓力測試,哪里有問題,給文件加密,并行就比串行快。

Node對異步IO的實現

  • 完美的異步IO應該是應用程序發起的非阻塞調用,無需通過遍歷或喚醒等方式輪詢。
node

幾個特殊的API

  • setTimeout和setInterval線程池不參與
  • process.nextTick()實現類似setTimeout(function(){},0);每次調用放入隊列中,在下一輪循環中取出。(在任何其他I / O事件(包括定時器)后續觸發中觸發之前運行,效率要比setTimeout高,它會先執行)
  • setimmediate();比process.nextTick()優先級低 上三者的區別
  • Node如何實現一個sleep?
async test(){
    console.log('1');
    await sleep(1);
    console.log('2');
}
sleep(time){
    return new Promise((resolve)=>{setTimeout(()=>{resolve()},time)})
}
test()
  • 哨兵變量
<script>
    // 哨兵變量
    var s = 0;
    var result;
    var arr = ['a.php','b.php','c.php'];
    for(var i = arr.length-1; i >= 0; i--){
        $.ajax({
            url:arr[i],
            success: function(){
                s = s + 1;
                if(s == 3){
                    alert(result);
                }
            }
        })
    }
    // 函數式編程
    $.ajax({
        url: arr[0]
    }).after()
</script>

函數式編程在node中的應用

  • 高階函數:可以將函數作為參數或返回值,形成一種后續傳遞風格的結果接收方式,而不是單一的返回值形式,后續傳遞風格的程序將函數業務重點從返回值傳遞到回調函數中。
app.use(function(){//todo});
var emitter = new events.EventEmitter();
emitter.on(function(){//todo});
  • 偏函數:指定部分參數形成一個新的定制函數的形式就是偏函數。Node中異步編程非常常見,我們通過哨兵變量會很容易產生業務的混亂。underscore,after變量

常用的Node控制異步技術手段

  • step、wind(提供等待的異步庫)、Bigpipe、Q.js
  • Async、Await
  • Promise/Defferred是一種先執行異步調用,延遲傳遞的處理方式。Promise是高級接口,事件是低級接口。低級接口可以構建很多復雜場景,但高級接口一旦定義,就無法改變,不再有地接接口的靈活性,但對于解決問題非常有效。(then就是Deffered模式)
  • 由于NodeV8的原因,目前還不支持協程。協程不是進程或線程,其執行過程更類似于子例程,或者說不帶返回值的函數調用。
  • 一個程序可以包含多個協程,可以對比與一個進程包含多個線程,因而下面我們來比較協程和線程。我們知道多個線程相對獨立,有自己的上下文,切換受系統控制;而協程也相對獨立,有自己的上下文,但是其切換由自己控制,由當前協程切換到其它協程由當前協程來控制。

內存管理與優化


  1. V8垃圾回收機制
  2. 常見內存泄露問題
  3. 內存泄露分析

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


  1. 經典的MVC框架
  2. NET多層架構
  3. JavaWeb多層架構

Node集群的應用


  1. 預備上線
  2. 多線程
  3. PM2
  4. 服務器集群

預備上線

  • 前端工程化搭載動態文件的MAP分析壓縮打包合并至CDN
  • 單測、壓測性能分析工具發現Bug
  • 編寫Nginx-conf實現負載均衡和反向代理
  • PM2啟動應用程序小流量灰度上線,修復BUG
  • 上線前不眠夜

多線程

  • NodeJS的多核處理是用cluster模塊處理的。

PM2

  • PM2是一個帶有負載均衡功能的Node應用的進程管理器。
  • 當你要把你的獨立代碼利用全部的服務器上的所有CPU,并保證進程永遠都活著,0秒重載。
  1. 內建負載均衡(使用Node cluster集群模塊)
  2. 后臺運行
  3. 0秒停機重載
  4. 具有Ubuntu和CentOS的啟動腳本
  5. 停止不穩定的進程(避免無限循環)
  6. 控制臺檢測
  7. 提供HTTP API
  8. 遠程控制和實時的接口API(Nodejs模塊,允許和PM2進程管理器交互)
pm2
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。