【问题标题】:Node.js + Socket.io + Redis app via PM2 with large memory footprintNode.js + Socket.io + Redis 应用程序通过 PM2 占用大量内存
【发布时间】:2016-01-10 04:17:33
【问题描述】:

我是 node.js 和 socket.io 的新手,但我正在尝试构建一个简单的服务来监听 Redis 通知(由 PHP 应用程序提供),并将它们广播给当前登录、连接的任何用户到 socket.io 房间,例如'site_name:user:user_id'。

我可以运行它,但是 Node 应用程序的内存占用很快变得越来越大,很快就从 100mb 增加到 200+mb,大约有 100 名用户在线并积极浏览,我想知道我是否有一些设置这里错了。

PM2 处理节点应用,nginx 设置为反向代理。

服务器端:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
var redisClient = redis.createClient();
var allClients = [];

server.listen(8890);

io.sockets.on('connection', function (socket) {
    allClients.push(socket);

    socket.on('subscribe', function(data) {
        console.log('Joining room', data.room);
        socket.join(data.room);
        redisClient.subscribe(data.room);
    })

    socket.on('disconnect', function() {
        console.log('Disconnect');
        var i = allClients.indexOf(socket);
        delete allClients[i];
    });

});

// Watch for connection errors and log
redisClient.on('error', function (err) {
    console.log('Error event - ' + redisClient.host + ':' + redisClient.port + ' - ' + err);
});

redisClient.on('message', function(room, message) {
    console.log('New message: ' + message + '. In room: ' + room);
    io.sockets.in(room).emit('message', message);
});

客户端:

// connect to socket
socket = io.connect('http://localhost:8890');

// subscribe to user's room once connected
socket.on('connect', function(data){
    socket.emit('subscribe', { room: site_name + ':user:' + user_id });
});

// show messages from user's "room" via redis notifications
socket.on('message', function (response) {
    var json = new Hash(JSON.decode(response, true) || {});
    roar.alert(json.title, json.message, { link: json.link });
});

看起来这应该是一个非常精简的应用程序,不是吗?一个简单的 node.js 应用程序的正常内存占用是多少?

服务器以 41mb 启动,但即使没有任何人连接它,内存也会缓慢增加,大约每分钟 1mb。一旦我开始连接用户,它会迅速膨胀到 200+mb,直到我杀死它。

我不清楚在用户连接和断开连接时如何最好地处理 redisClient 和套接字连接,我认为这可能是问题所在。但是看到它在空闲时爬升令人不安。

  • PM2 v0.15.7
  • 节点 v0.12.7
  • socket.io v1.3.7
  • express v4.13.3
  • nginx v1.6.2

非常感谢任何帮助。

【问题讨论】:

  • 我看到很多关于升级到 Node v4.x 修复内存泄漏的帖子,所以我将 Node 更新到 4.1.2。我肯定会看到更好的内存性能和更频繁的 GC,但它的大小仍然缓慢增长。然而,它现在徘徊在 90/80mb 左右,而不是 200+mb。

标签: node.js sockets memory socket.io pm2


【解决方案1】:

我有一个类似的设置,虽然它还没有发布,也没有做压力测试......但这里有一个想法给你:

为 socketio 使用 redis 模块(是否有更好的 redisClient 会很有趣)。它使用不同的客户端进行发布和订阅。 subClient 使用detect_buffers。

var redisModule = require('socket.io-redis');
var redisAdapter= redisModule({
      host: redisClient.options.host
    , port: redisClient.options.port
    , pubClient: redisClient
    //, subClient: ... separate client that uses detect_buffers
});
io.adapter(redisAdapter);

然后订阅/断开连接看起来像这样:

socket.on('subscribe', function(room) {
    socket.join(room);
});
socket.on('disconnect', function() {
    console.log('user disconnected');
});

我也多次读到,socketio 不是最好的,而是使用 sockjs。不知道是否仍然如此。

而且...因为我刚刚意识到已经超过 2 个月了。您是否找到任何可以减少内存占用的方法?

【讨论】:

  • 自从几个月前将它推送到生产服务器后,我就再也没有回过头来。目前两个 pm2 实例使用 320mb 和 340mb。 (我刚刚运行pm2 restart all,它们每个都下降到约 60mb。)它们也徘徊在 4% 到 9% 之间,尽管这个应用程序几乎没有做任何事情。下次我在这个网站上工作时,我会尝试你的建议,看看它是否有什么不同。谢谢!
  • 另一个使用 ElephantIO (elephant.io/#usage) 的想法,但它会将 Redis 排除在可能需要也可能不需要的等式之外。
猜你喜欢
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 2013-05-30
相关资源
最近更新 更多