Nodejs 内存一直涨,并且下不去

Nodejs 内存一直涨,并且下不去

创建了一个服务,功能只是坚挺了一个端口,我没10秒输出一次内存,发现内存不停的涨,偶尔下去一点点,后又上来了。不知道如何解决

23 回复

Node.js 内存一直涨,并且下不去

问题描述

你创建了一个简单的 Node.js 服务,该服务只监听一个端口,并且每10秒输出一次当前的内存使用情况。你发现内存占用一直在增加,即使有时会下降一点,但很快又会上升。这种情况可能是由于多种原因引起的。

可能的原因及解决方案

  1. 内存泄漏

    • 原因:如果你的应用程序中存在未被及时回收的对象引用,那么这些对象将不会被垃圾回收器回收,从而导致内存不断增长。
    • 解决方案:检查是否有全局变量或闭包导致对象引用无法被释放。可以使用 process.memoryUsage() 来监控内存使用情况,并使用工具如 memwatch-nextheapdump 来分析内存泄漏。
  2. 频繁的内存分配

    • 原因:如果应用程序频繁地创建新的对象而没有及时清理,也会导致内存使用不断增加。
    • 解决方案:尝试复用对象,减少不必要的内存分配。例如,使用对象池来管理频繁创建的对象。
  3. 缓存问题

    • 原因:如果应用程序中有大量的缓存数据,而这些数据没有被及时清理,也会导致内存使用不断增加。
    • 解决方案:确保缓存机制有适当的过期策略,或者使用 LRU(最近最少使用)等算法来管理缓存。

示例代码

const http = require('http');
const memwatch = require('memwatch-next');

// 启动内存监控
memwatch.on('stats', (stats) => {
    console.log(stats);
});

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello World\n');
});

server.listen(3000, () => {
    console.log('Server running at http://localhost:3000/');

    // 每10秒输出一次内存使用情况
    setInterval(() => {
        const memoryUsage = process.memoryUsage();
        console.log(`RSS: ${memoryUsage.rss} Bytes`);
        console.log(`Heap Total: ${memoryUsage.heapTotal} Bytes`);
        console.log(`Heap Used: ${memoryUsage.heapUsed} Bytes`);
    }, 10000);
});

解释

  • 内存监控:使用 memwatch-next 库来监控内存泄漏。
  • HTTP 服务器:创建一个简单的 HTTP 服务器,监听端口 3000。
  • 定时输出内存使用情况:使用 setInterval 每10秒输出一次当前的内存使用情况,包括 RSS、堆总大小和堆已使用大小。

通过以上方法,你可以更好地理解并解决 Node.js 应用中的内存泄漏问题。


上代码,上代码,上代码。。。。。。。。。。 应该是内存泄漏了吧

 var mNet = require('net');
 var mCpuCount = require('os').cpus().length;
 var mCluster = require('cluster');
 var mLogo=require('../logs/log_system');
 var mPackageSystem=require('../shared/packageSystem');

 function GameMain(aPort){
     if(mCluster.isMaster==true){

      mNet.createServer(function(sock){
	
	  console.log('连接');
	
	 sock.on('data', function(data) {
		
	 });
	
	/** 断开连接*/
	sock.on('close', function(data) {
		 console.log("断开后");
	});
	
	sock.on('error', function(error) {
		
	});
	
}).listen(aPort);
console.log("game_server starting port:"+aPort);
}

}

其他的什么也没写

每次连接 、断开都会涨,断开后涨的特别的明显,始终下不去

贴代码了

在 sock.on(‘error’,function(error)) {

} 增加了sock.destroy(); 也不好用 T_T

每次调用GameMain(aPort),都会创建新的进程。 而断开连接时没有kill掉。

GameMain(aPort) 只调用了一次。 你说的kill是什么意思~

没看出来你那个代码有什么问题(你应该是删了一部分吧?)。 如果可以的话,尽量把没用的或者不必要的删掉,然后自己再测试一下。 还有你是怎么测试的,也应该说清楚。

单纯的监听 应该没有什么问题。 不知道你的 子进程在做什么?

因为我最近也有用cluser,几十万连接,内存也没有这么大。

代码是全的。 if(mCluster.isMaster==true)这个只是判断了一下,没有启动子进程。 测试过程就是 打开服务监听,启动的时候内存大概是16000左右,连接了1000个长连接,每个连接一直发送128K的数据,此时内存大概会在21000左右,断开连接后,内存还是21000左右,并没有随着我的断开连接恢复到16000左右

补充下,测试过程 if(mCluster.isMaster==true)这个只是判断了一下,没有启动子进程。 测试过程就是 打开服务监听,启动的时候内存大概是16000左右,连接了1000个长连接,每个连接一直发送128K的数据,此时内存大概会在21000左右,断开连接后,内存还是21000左右,并没有随着我的断开连接恢复到16000左右

几十万的内存大概是多少呢~

16000的单位是K吗,是rss还是heap? 如果是K,别纠结了,这是再正常不过。如果是M,呃呃呃…

昨天晚上挂了一夜,开了3台机器,连接数加到了1500。 三台机器最少每秒发送28K数据,最大发送128K数据 数据如下 刚启动的时候 [2013-05-21 21:36:42.244] [INFO] log -23912448 然后每10秒log一次内存到在今天早上 [2013-05-22 07:06:31.561] [INFO] log - 58814464 [2013-05-22 07:06:41.560] [INFO] log - 58834944 [2013-05-22 07:06:51.563] [INFO] log - 58834944 [2013-05-22 07:07:01.559] [INFO] log - 58834944 [2013-05-22 07:07:11.571] [INFO] log - 58834944 [2013-05-22 07:07:21.570] [INFO] log - 58834944 关闭连接后依旧保持这些内存无变化。

也就是说,每次连接都会有内存释放不掉。这样反反复复的内存早晚要溢出的。

你销毁连接后,内存能回到为连接的时候的内存么

难道没人能给解决或者是解释一下么

到早上内存不是已经稳定了吗? 这时仍在1500个连接每秒28K的发包吧 很正常不是

V8在负载高的时候不爱执行GC的; 你说断开连接是不是断开了所有连接,让它0负载再观察一下。 不回收是不可能的

1500连接?再多点,上万,然后连接=》发数据=》断开=》连接=》发数据=》断开,如此往复多次…… 可以参考一下这个:http://cnodejs.org/topic/50e5900da7e6c6171a0159d7,我目前自己做长连接服务的测试结果大概是,每连接10K内存,没有内存泄露问题(你的代码也不像有。。)

你发的帖子,已经被删除了。

就是断开了所有的连接,0负载,可是还是下不去。

当Node.js应用中的内存持续增长时,通常是因为存在内存泄漏问题。这可能是由于长时间运行的对象没有被正确回收,或者有循环引用等问题。以下是一些可能的原因和解决办法:

1. 检查内存泄漏

首先,可以使用memwatch-next库来检测内存泄漏。这是一个用于查找Node.js中内存泄漏的工具。

安装memwatch-next

npm install memwatch-next --save-dev

然后,在你的应用中添加以下代码来检测内存泄漏:

const memwatch = require('memwatch-next');

memwatch.on('leak', (info) => {
    console.error('Memory leak detected:', info);
});

2. 使用 process.memoryUsage()

你可以定期检查内存使用情况以追踪泄漏情况:

setInterval(() => {
    const memoryUsage = process.memoryUsage();
    console.log(`Heap Used: ${memoryUsage.heapUsed / 1024 / 1024} MB`);
}, 10000); // 每10秒检查一次

3. 避免全局变量

确保没有全局变量或闭包导致对象无法被垃圾回收。例如,避免在回调函数中保存不必要的数据。

// 错误示例
let globalVar;
app.get('/', (req, res) => {
    globalVar = req.query.data; // 这会导致内存泄漏
    res.send('Hello World');
});

4. 使用弱引用

如果必须保存大量对象引用,考虑使用WeakMapWeakSet

const weakMap = new WeakMap();

function someFunction(obj) {
    weakMap.set(obj, 'some data');
}

5. 优化代码

确保没有未释放的资源,如数据库连接、文件句柄等。使用适当的关闭逻辑。

6. 重启服务

作为临时解决方案,可以设置自动重启机制,比如使用PM2进程管理器。

pm2 start app.js --watch --max-memory-restart 200M

以上方法可以帮助你定位并解决内存泄漏问题。如果问题仍然存在,建议详细检查你的代码逻辑,特别是涉及到异步操作和事件监听的地方。

回到顶部