Node內存泄漏的那點事

讀書筆記:沒有理由去強烈堅持本身選擇的技術就是最好的,而輕視甚至無視其餘技術。若是執拗己見,最終受損的的你本身。若是你願意對技術保持開放的心態,而不是固守本身已經瞭解的技術,聲稱它是最好的,你會發現有更多的機會爲你敞開大門。~~~node

內存泄漏

node 對內存泄漏十分的敏感,有成千上萬的流量下,一個字節的泄漏都會形成堆積,在垃圾回收時,掃描對象時耗時更多,影響整個應用的響應時間,知道進程內存溢出,應用崩潰。數據庫

形成內存溢出的因素:數組

  • 緩存
  • 隊列消費不及時
  • 做用域未釋放

緩存(謹將內存當緩存)緩存

  • 緩存在應用中的做用佔很重要的地位,能夠十分有效的節省資源。若有命中緩存,能夠節省一個I/O的時間
  • Node中若用一個對象當作緩存,則它將常駐老生代。若緩存的鍵多,長期存活的對象也多,致使垃圾回收時對這些對象作無用功。影響整個應用。
  • JS開發者喜歡用一個對象的鍵值來緩存東西,嚴格意義上和緩存又存在這區別,嚴格的緩存有相應的過時策略,而對象沒有。受垃圾回收機制的影響,對象作緩存只能小量使用。
  1. 緩存的限制策略

爲了解決緩存中對象沒法釋放的問題,須要加入一種策略來限制緩存的無限增加bash

var LimitableMap = function (limit) { 
     this.limit = limit || 10; //限制相應的大小
     this.map = {}; 
     this.keys = []; 
    }; 
    var hasOwnProperty = Object.prototype.hasOwnProperty; 
    LimitableMap.prototype.set = function (key, value) { 
     var map = this.map; 
     var keys = this.keys;
     if (!hasOwnProperty.call(map, key)) { 
         if (keys.length === this.limit) { 
             var firstKey = keys.shift(); //當超過大小時,就作出隊列處理
             delete map[firstKey]; 
         } 
         keys.push(key); 
    } 
         map[key] = value; 
    }; 
    LimitableMap.prototype.get = function (key) { 
     return this.map[key]; 
    }; 
module.exports = LimitableMap;
複製代碼
  • 模塊機制形成的內存泄漏,解決策略

模塊的引入,爲了加速模塊的引入,全部的模塊都會進行編譯執行,緩存起來,由exports導出的函數,能夠訪問文件模塊中的私有變量,這樣子文件模塊編譯執行生成的做用域由於模塊的緩存而不會被釋放。因爲模塊的緩存機制,模塊是常駐老生代的。(要十分當心內存泄漏)dom

var leakArray = []; 
    exports.leak = function () { 
        leakArray.push("leak" + Math.random()); 
    };
    <!--每次外部調用leak時, leakArray 會一直增長,不停的佔用內存,且不被釋放。-->
複製代碼

若模塊不可避免的要使用上面的設計,那麼就添加一個清空隊列的接口。異步

  1. 緩存的解決方案

直接將內存做爲緩存要十分謹慎,一不當心就會有不少的問題函數

  • 要限制緩存的大小,否則對垃圾回收,以及內存空間都有很大的影響
  • 進程間沒法貢獻內存信息(緩存的信息)
  • 每個進程都有一個緩存,對物理內存的使用是一種浪費。
  • 解決方案
    • 若大量使用緩存,比較好的解決方案就是用進程外的緩存,進程自身不緩存狀態。外部的緩存有良好的緩存過時淘汰策略和內存的管理,不影響node進程的性能。
    • Redis 和 Memcached

關注隊列的狀態性能

在解決了緩存帶來的內存泄漏後,另外一個不經意會產生內存泄漏的就是隊列ui

  • JS能夠經過隊列(數組對象)來完成一些特殊的需求,其在消費者-生成者中常常充當中間產物。
  • 在大多數狀況下:消費的速度遠遠大於生成的速度,內存不易泄漏。可是一旦消費速度小於生成速度,將會形成堆積。
  • 舉個栗子: 寫日誌,若用數據庫來存日誌,日誌一般是海量的,數據庫建在文件系統上,寫入效率遠低於文件寫入,因而就造成數據庫寫入堆積,Js的做用域也不會獲得釋放,內存佔用不會回落,形成內存泄漏。
  • 解決方法: 1. 用文件寫入,可是也存在內存泄漏的狀況(生成速度因某些緣由劇增,或消費因某些緣由驟減)。 2.監控隊列的長度,一旦出現堆積,就警報,通知開發人員。或者在異步調用里加入超時機制。一旦超時就傳遞超時異常。
相關文章
相關標籤/搜索