使用 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?
使用 Socket.IO 将 Node.JS 服务器连接到另一个 Node.JS 服务器?