关于Node的内存泄漏简析

2017-12-14 23:32:44邵晨龙江雪
中国科技博览 2017年46期
关键词:调用队列日志

邵晨龙++江雪

[摘 要]Node对内存泄漏十分敏感,一旦线上应用有成千上万的流量,哪怕是一个字节的内存泄漏也会造成堆积,垃圾回收过程中将耗费更多时间进行对象扫描,应用响应缓慢,直到进程内存溢出,应用崩溃。本文不仅分析了造成内存泄漏的原因,并介绍了几种主流的排查方案。

[关键词]Node 内存泄漏

中图分类号:TG294 文献标识码:A 文章编号:1009-914X(2017)46-0046-01

1 引言

内存泄漏通常产生于无意间,较难排查。尽管内存泄漏的情况不尽相同,但其实质只有一个,那就是应当回收的对象出现意外而没有被回收,变成了常驻在老生代中的对象。

2 引发内存泄漏的原因

通常,造成内存泄漏的原因主要有两个:缓存,队列消费不及时。

2.1 缓存

缓存在应用中的作用举足轻重,可以十分有效地节省资源。因为它的访问效率要比I/O的效率高,一旦命中缓存,就可以节省一次I/O的时间。

但是在Node中,缓存并非物美价廉。一旦一个对象被当作缓存来使用,那就意味着它将会常驻在老生代中。缓存中存储的键越多,长期存活的对象也就越多,这将导致垃圾回收在进行扫描和整理时,对这些对象做无用功。

另一个问题在于,JavaScript开发者通常喜欢用对象的键值对来缓存东西,但这与严格意义上的缓存又有着区别,严格意义的缓存有着完善的过期策略,而普通对象的键值对并没有。所以,在Node中,任何试图拿内存当缓存的行为都应当被限制。当然,这种限制并不是不允许使用的意思,而是要小心为之。

为了解决缓存中的对象永远无法释放的问题,需要加入一种策略来限制缓存的无限增长,例如将记录键记录在数组中,一旦超过数量,就以先进先出的方式进行淘汰,这种策略适合于小场景的案例中使用,在比较大型的应用场景一般使用的是基于LRU(最近最少使用)算法的策略。

除了限制缓存的大小外,还需要考虑到进程间是无法共享内存的。如果在进程内使用缓存,这些缓存不可避免地有重复,对物理内存的使用是一种浪费。目前较好的解决方案是采用进程外的缓存,进程自身不存储状态。外部的缓存软件有着良好的缓存过期淘汰策略以及自身的内存管理,不影响Node进程的性能。市面是较好的缓存有Redis和Memcached。

2.2 队列

在解决了缓存带来的内存泄漏问题后,另一个不经意产生的内存泄漏则是队列。在JavaScript中可以通过队列(数组对象)来完成许多特殊的需求,比如Bagpipe。队列在消费者-生产者模型中经常充当中间产物。这是一个容易忽略的情况,因为在大多数应用场景下,消费的速度远远大于生产的速度,内存泄漏不易产生。但是一旦消费速度低于生产速度,将会形成堆积。

举个例子,有的应用会收集日志。如果欠缺考虑,也许会采用数据库来记录日志。日志通常会是海量的,数据库构建在文件系统之上,写入效率远远低于文件直接写入,于是会形成数据库写入操作的堆积,而JavaScript中相关的作用域也不会得到释放,内存占用不会回落,从而出现内存泄漏。

遇到这种场景,表层的解决方案是换用消费速度更高的技术。在日志收集的案例中,换用文件写入日志的方式会更高效。但是,如果生产速度因为某些原因突然激增,或者消费速度因为突然的系统故障而降低,内存泄漏还是可能会出现。

深度的解决方案应该是监控队列的长度,一旦堆积,应当通过监控系统产生报警并通知相关人员。另一个解决方案是任意异步调用都应该包含超时机制,一旦在限定的时间内未完成响应,通过回调函数传递超时异常,使得任意异步调用的回调都具备可控的响应时间,给消费速度一个下限值。

对于Bagpipe而言,它提供了超时模式和拒绝模式。启用超时模式时,调用加入到队列中就开始计时,超时就直接响应一个超时错误。启用拒绝模式,当队列拥塞时,新到来的调用会直接响应拥塞错误。这两种模式都能够有效地防止队列拥塞导致的内存泄漏问题。

3 內存泄漏的排查方案

在Node中,由于V8的堆内存大小的限制,它对内存泄漏非常敏感。当在线服务的请求量变大时,哪怕是一个字节的泄露都会导致内存占用过高。

常见的用于排查Node应用内存泄露的有以下几个工具:

*v8-profiler,用于对V8堆内存抓取快照和对CPU进行分析;

*node-heapdump,允许对V8堆内存抓取快照,用于事后分析,这是Node核心贡献者编写的模块;

*node-mtrace,它使用了GCC的mtrace工具来分析堆的使用;

*node-memwatch,来自Mozilla的LloydHilaiel贡献的模块,采用WTFP许可发布。

4 总结

所谓知己知彼,百战不殆,只有深入了解了造成内存泄漏的主要原因,才能对症下药,尽可能地规避造成内存泄漏的行为,并采用主流的工具予以排查消除隐患。endprint

猜你喜欢
调用队列日志
一名老党员的工作日志
华人时刊(2021年13期)2021-11-27 09:19:02
扶贫日志
心声歌刊(2020年4期)2020-09-07 06:37:14
队列里的小秘密
基于多队列切换的SDN拥塞控制*
软件(2020年3期)2020-04-20 00:58:44
核电项目物项调用管理的应用研究
在队列里
LabWindows/CVI下基于ActiveX技术的Excel调用
测控技术(2018年5期)2018-12-09 09:04:46
游学日志
丰田加速驶入自动驾驶队列
基于系统调用的恶意软件检测技术研究