我读到过,node.js websocket 模块 ws 和 socket.io 都存在内存泄漏。这个问题已经存在好几年了,我想知道该如何修复它。
下面提到了其中的一些:
- https://github.com/socketio/socket.io/issues/2427(已关闭但无解决方案)
- https://github.com/socketio/socket.io/issues/3477(设置 perMessageDeflate:false 显然有帮助,但根本原因是碎片问题,这显然不是由 websocket 库或节点引起的,而是由它们的运行方式引起的,可以通过预加载 jemalloc 来解决)
- https://github.com/nodejs/node/issues/8871#issuecomment-250915913(此处提供相同的解决方案)
- https://github.com/websockets/ws/issues/804(看来问题已经解决了,只需将 perMessageDeflate 设置为 false - 无需 jemalloc)
鉴于现在是 2021 年,将 perMessageDeflate 键设置为 false 并预加载 jemalloc 仍然是最好的解决方案吗?
答案1
我对这个问题的初步理解如下(不要引用我的话):
- ws node.js 模块(即 websockets 模块)和 socket.io node.js 模块都使用另一个名为 zlib 的模块。此模块负责在通过 websocket 发送消息时对其进行压缩。
- zlib 模块过去曾出现过与内存碎片有关的问题,它模仿了内存泄漏(即,它实际上不是内存泄漏而是内存碎片)。
- 服务器上默认禁用消息压缩,但客户端(例如浏览器)默认启用。如果我们禁用它,则不使用 zlib 模块,这将消除内存碎片问题。
- 为了在客户端(例如浏览器)上禁用压缩,我们
perMessageDeflate
在服务器代码中为键赋予值false
。即:
const wss = new WebSocket.Server({ server:httpsServer, perMessageDeflate: false });
显然,对于那些想要压缩消息的人来说,这不是一个解决方案。但值得一提的是:
- zlib 的内存碎片问题显然已得到部分修复https://github.com/websockets/ws/pull/1204但这似乎仍然是一个问题;
- 压缩小消息(例如小段文本)的好处一直存在争议。有些人甚至表示压缩小消息会使速度变慢。如果您要处理较大的数据(例如图像或视频),您可以在通过 websocket 发送之前自行压缩(即不使用 ws/socket.io/zlib)以取得成功。
此外,有人指出,设置 perMessageDeflate: false 只能减少问题,但不能完全解决问题。我想请您注意这个讨论,其中说打开和关闭 websocket 时的一些残留和恒定(即不增加)内存使用是正常的(顺便说一句,我不一定说这是正确的):https://github.com/websockets/ws/issues/804#issuecomment-302612661
至于预加载 Jemalloc,这似乎并不能解决问题。但如果上述代码不起作用,那么肯定值得研究(或尝试)。
那么这是preMessageDeflate: false
目前最好的解决方案吗?根据我的理解,我认为是的。
如果有人对此有更正或更多信息,请添加。