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.监控队列的长度,一旦出现堆积,就警报,通知开发人员。或者在异步调用里加入超时机制。一旦超时就传递超时异常。
相关文章
相关标签/搜索