以下内容由PM2在Ubuntu计算机上作为服务运行。内存占用量从40MB稳步上升到95MB,此时服务器停止发射,但不会导致PM2进程崩溃。这导致网页无响应。
此代码只是在收到Tweet时发送套接字发送。当没有人连接但内存使用率仍然增加时,它不会发生事件,因此它可能与SocketIO无关。
只是想知道client.stream中的哪些内容可能导致此泄漏。我安装了memwatch但没有出现。
var express = require('express');
var Twitter = require('twitter');
var login = require('./credentials');
var connections = 0;
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static('public'));
String.prototype.startsWith = function(str){
return this.indexOf(str) === 0;
};
var client = new Twitter({
consumer_key: login.creds['consumer_key'],
consumer_secret: login.creds['consumer_secret'],
access_token_key: login.creds['access_token_key'],
access_token_secret: login.creds['access_token_secret']
})
client.stream('statuses/filter', {track: 'drake'}, function(stream) {
stream.on('data', function(tweet) {
var imageUrl = undefined;
try {
imageUrl = tweet.entities.media[0].media_url;
}
catch(err) {
// Ignored
}
abridgedTweet = {'text': tweet.text, 'author': tweet.user.screen_name, 'picture': imageUrl};
if (connections > 0 && !(tweet.text.startsWith("RT")) && !(tweet.text.startsWith("@")) && tweet.lang == "en") {
io.emit('tweet', abridgedTweet);
};
});
stream.on('error', function(error) {
console.log("ERROR: " + error);
})
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('A user connected');
connections += 1;
socket.on('disconnect', function() {
console.log("A user disconnected");
connections -= 1;
console.log(connections + " users remaining");
});
});
http.listen(3000, function(){
console.log('listening on *:3000, pid: ' + process.pid);
});
编辑:我从stream.on('数据')块中删除了所有内容,内存使用量仍在增加。
答案 0 :(得分:2)
这是人们在开始使用PM2时能够清楚地看到内存使用情况的常见问题。 Node.js使用谷歌的V8 JavaScript引擎,它实现了垃圾收集器。 V8使用的GC算法将尝试占用尽可能多的内存,并且在清理未使用的内存时非常懒惰。因此,通常情况下,节点进程将继续增加内存使用量,直到GC认为更好地释放内存的某个点。请注意,节点进程的硬内存限制为1.4 GB。
有一种方法可以使用--expose-gc
标志强制GC释放内存。像这样运行你的服务器:
node --expose-gc yourscript.js
并在应用程序的某处附加以下循环。这将每30秒强制进行垃圾收集。
setInterval(function(){
global.gc();
console.log('GC done')
}, 1000*30);
如果你正在使用PM2,你需要做额外的工作来传递--expose-gc
标志。注意在实践中你可能应该避免做手动垃圾收集,然后让我们V8完成它的工作。
其次,尽管显然没有做任何事情,你的过程首先增加的原因可能是PM2本身。默认情况下,PM2以群集模式运行,而不是fork模式。群集模式将在后台运行某些进程,从而随着时间的推移增加内存。这个内存最终会在某些时候由GC解除分配。如果在fork模式下运行PM2,则当进程空闲时,内存占用应保持在同一级别。