使用Socket.IO + Node.js + ZMQ发出消息时出现内存泄漏问题

46

我有三个相互交流的应用程序。一个websocket服务器(1)接受来自浏览器的连接,解析url以查看所需的数据,并在内存中提供它以供客户端使用;如果没有,则从另一个名为“fetcher”的应用程序(2)请求该数据。Fetcher接收此工作,从简单的API(3)请求它并返回JSON数据,然后将其发送回到Websocket服务器,该服务器将其发布到连接的客户端。然后,“fetcher”开始定期检查URL/任务是否有更新,并在发生更新时将新数据发送到websocket服务器。

我使用socket.io进行客户端-WebSocket服务器通信。 WebSocket服务器和fetcher通过 ZMQ 套接字进行通信。

我使用 130个连接对websocket服务器进行负载测试。 Websocket服务器每秒向130个客户端发布160KB的数据。一开始,对于130个连接,它使用170MB的RAM,但很快就增加到1GB,尽管没有新的连接。然后,socket.io的心跳信号开始失败,导致连接断开。

我使用Nodetime拍摄堆快照。第130个客户端连接后,内存的情况如下:

“输入图像说明”

共有 346个Buffer对象,总计 44MB

在四分钟内,缓冲区对象的数量急剧增加(同样,没有新的连接):共有3012个缓冲区对象,总内存为 486MB 。再过10分钟,有3535个缓冲区对象,总内存消耗量为 573MB

我使用Mozilla的memwatch找出哪一行会导致内存增加,并发现是这个函数:

function notifyObservers(resourceId) {
  var data = resourceData[resourceId];
  io.sockets.in(resourceId).emit('data', data);
}
如果我将这些行注释掉,内存使用量保持不变,这是另一个确认。你有什么想法这是如何发生的吗?我在ZMQ的订阅者套接字方法中调用此函数,我怀疑这与此有关。如果我删除函数并将它们合并为一个函数,则会得到以下代码:
// Receive new resource data
const resourceUpdatedSubscriber = zmq.socket('sub').connect('tcp://localhost:5433');
resourceUpdatedSubscriber.subscribe('');

resourceUpdatedSubscriber.on('message', function (data) {
  var resource = JSON.parse(data);

  resourceData[resource.id] = resource.data;

  io.sockets.in(resourceId).emit('data', resourceData[resource.id]);
});

我的所有代码(包括负载测试)都是公开的,您可以在此处找到此 WebSocket 服务器:https://github.com/denizozger/node-socketio/blob/master/server.js请查看第138行。

我两个月前开始学习 JavaScript 和 Node.js,所以欢迎任何评论。谢谢!


2
这可能不是最终解决方案,但肯定是进一步调查的好指针: 1)http://www.tuicool.com/articles/yUR3q2 2)https://github.com/jmatthewsr-ms/node-slab-memory-issues - shoen
非常感谢Dawid,虽然这些看起来不是最终解决方案,但它们给了我灵感。我用以下简单的代码再次复制:resourceUpdatedSubscriber.on('message', function (data) { io.sockets.emit('data', data); }); 重要的是:如果我静态地提供相同的数据(即 var bigData = require('./bigdata.json');),我就没有任何问题。每当我使用来自ZMQ发布者并进行“emit”的数据时,我就会遇到内存问题。仍在努力解决中... - Deniz Ozger
1
快速更新,仅提供静态JSON会延迟问题。在230个观察者时,内存泄漏再次显现。 - Deniz Ozger
2
我使用Engine.IO(https://github.com/denizozger/node-engine.io-server)重新实现了应用程序。问题仍然存在,但这次是在超过210个用户(每秒35MB数据传输)的情况下。 - Deniz Ozger
你是如何找到Mozilla的node-memwatch中确切的问题行的? - Deyan Vitanov
显示剩余4条评论
2个回答

2

0

或许尝试添加

var resourceData;

在你的代码中某个地方,因为也许你的内存泄漏与全局变量有关

在这里阅读更多关于全局变量的信息:https://gist.github.com/hallettj/64478


我不确定你的回答是否是最佳答案,但是参考的代码片段确实很棒。 - HeadCode
resouceData在这一行已经被定义了:https://github.com/denizozger/node-socketio/blob/master/server.js#L54 - Deniz Ozger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接