我有一个遇到内存泄漏的Node.js
服务器。它使用socket.io
向连接的客户端发送消息。我已经设置了一个每分钟向客户端发送一次消息的函数。功能是:
var message = "smile";
const doEveryMinute = (socket) => {
setTimeout(() => {
setInterval(() => doEveryMinute(socket), 6000);
socket.emit('smile', message);
}, (60 - date.getSeconds()) * 1000);
}
当用户通过io.on
函数连接时调用该函数:
io.on('connection', function (socket){
doEveryMinute(socket);
});
我不明白为什么这会导致内存泄漏,但肯定会导致内存泄漏。我可以在htop
看到ram缓慢但肯定会填满,直到服务器崩溃显示memory overflow exception
消息。
为什么此代码会导致内存泄漏?
答案 0 :(得分:1)
首先,6000是6秒,而不是60秒。
您永远不会致电clearInterval
,因此您使用setInterval
创建的计时器将永远停留,每6秒调用一次。请记住,这是setInterval
,而不是setTimeout
,因此定时器在第一次触发后不会停止。
本身并不一定是个问题,因为单个计时器的内存使用量可以忽略不计。
但是,计时器调用的函数调用doEveryMinute
,这将创建另一个计时器。随着每个计时器在6秒后创建另一个计时器,它将呈指数级增长。
如果您只想每60秒发送一条消息,则不需要递归,只需一个调用emit
的计时器:
var message = "smile";
const doEveryMinute = (socket) => {
setTimeout(() => {
setInterval(() => socket.emit('smile', message), 60000);
}, (60 - date.getSeconds()) * 1000);
}
请注意,这仍然不是完美的,因为它永远不会停止计时器,您需要在连接断开时向clearInterval
添加合适的呼叫。我对于setInterval
在60年代后开火的可靠性做出了一些可疑的假设。我想知道你的原始代码是否试图处理定时器的不精确性?这没关系,但如果你想这样做,你需要坚持setTimeout
而不是setInterval
。