使用 Socket.IO + Node.js + ZMQ 发送消息时发生内存泄漏

Posted

技术标签:

【中文标题】使用 Socket.IO + Node.js + ZMQ 发送消息时发生内存泄漏【英文标题】:Memory leak when emitting messages with Socket.IO + Node.js + ZMQ 【发布时间】:2014-01-01 05:34:00 【问题描述】:

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

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

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

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

346 个缓冲区对象,总共 44MB

在四分钟内,Buffer 对象的数量急剧增加(同样,没有新连接):共有 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]);
);

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

两个月前我开始学习 javascript 和 Node.js,所以欢迎任何 cmets,提前谢谢!

【问题讨论】:

这可能不是最终的解决方案,但肯定是进一步调查的好指针:1) tuicool.com/articles/yUR3q2 2) github.com/jmatthewsr-ms/node-slab-memory-issues 非常感谢 Dawid,确实这些似乎不是最终解决方案,但它们启发了我。我用这些简单的行再次复制:resourceUpdatedSubscriber.on('message', function (data) io.sockets.emit('data', data); ); 重要的一点是:如果我静态提供相同的数据(即var bigData = require('./bigdata.json');,我没有任何问题。每当我使用来自 ZMQ 发布者的数据并 'emit ' 它,然后我有内存问题。仍在努力...... 快速更新,提供静态 json 只会延迟问题。在 230 观察者内存泄漏再次明显.. 我用 Engine.IO (github.com/denizozger/node-engine.io-server) 重新实现了应用程序。问题仍然存在,但这次有超过 210 个用户(35MB 数据传输/秒)。 这有什么更新吗?自 12 月以来,Node 已经解决了一些内存泄漏问题,您是否有任何改进,或者您是否发现并修复了任何具体问题? 【参考方案1】:

NodeJs 可能使用 Windows Socket API(其中包括内存泄漏,旧的已知错误) https://connect.microsoft.com/VisualStudio/feedback/details/605621/winsock-c-program-causes-memory-leak

问题是在您关闭网络服务之前永远不会调用 WSACleanup。 (混合 ZMq 或 Nodejs 不会改变这一事实)

现在,随着时间的推移,您将锁定更多的内存页,并且在第一个内存页满后这种通知会增加。

【讨论】:

【参考方案2】:

可以试试添加

var resourceData;

在您的代码中某处,因为您的内存泄漏可能与全局变量有关

在此处阅读有关全局变量的更多信息:https://gist.github.com/hallettj/64478

【讨论】:

不确定您的答案是否是答案,但参考的要点是一本很好的读物。 resouceData 实际上已经在该行定义:github.com/denizozger/node-socketio/blob/master/server.js#L54

以上是关于使用 Socket.IO + Node.js + ZMQ 发送消息时发生内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io 使用 node.js,根本没有 express?

Node.js 和 socket.io 的混淆

使用 Socket.IO 将 Node.JS 服务器连接到另一个 Node.JS 服务器?

node.js + socket.io:拍卖网站开发

如何将 Asterisk ARI 与 socket.io 和 Node.js 一起使用

Node.js、多线程和 Socket.io