node.js - 在数组中存储 WebSocket 消息时堆内存不足
问题描述
我正在用 Node.js 编写一个 WebSocket 客户端,并且我想对消息数据执行异步操作(即存储在数据库中),但还要确保消息按照它们的顺序一次操作一个已收到。
为了实现这一点,我将消息推送到我的 onMessage 处理程序中的数组,同时使用调用自身的函数一次将消息从数组中移出。像这样的东西:
const flushQueue = async () => {
const nextMessage = messageQueue.shift();
await doSomethingAsync(nextMessage); // i.e. store in db, etc.
flushQueue();
}
抛开我的系统能否跟上这个问题,这种方法效果很好,只是脚本最终会耗尽堆内存。一个简单的测试表明,将一个元素从数组中移出实际上会增加使用的堆内存量,而我的假设是它减少了使用的内存:
const a = [1,2,3,4,5,6];
a.shift();
a.shift();
console.log(process.memoryUsage());
为什么从数组中删除元素会增加进程使用的内存量?如何以一种内存有效的方式无限期地存储我的一组排队的 WebSocket 消息?
解决方案
我几乎可以肯定问题出在你的尾声中,而不是移动数组。Node 和 Javascript 没有适当的尾调用优化。一些统计数据和TCO 上的帖子。
没有尾调用优化的长时间运行循环最终会耗尽内存。
我会删除这个自定义队列,并直接写入数据库。
SQLite + better-sqlite3驱动程序是一个很好的起点。
// pseudo-code example (not tested)
ws.on('message', function incoming (data) {
const stmt = db.prepare('INSERT INTO list(message) VALUES(?)')
const result = stmt.run(data) // synchronous in-process write
// do something with result or something else
});
推荐阅读
- python-3.x - 尝试创建新笔记本时出现此错误
- c# - 如何以编程方式重新排序、隐藏、取消隐藏 Chrome 工具栏上的扩展图标
- android - react-native - keyboardDidShow 和 keyboardDidHide 在 Android 中屏幕旋转时触发
- java - 如何在 POST 后修复空白页以在 Java EE 中将数据插入数据库
- android - 为 Button 添加 onClickListener 时出现编译错误
- javascript - 使用javascript或python正则表达式我想确定数字是否为1-99如何制作?
- spring-boot - 用于构建 spring-cloud-dataflow-server 映像的 Dockerfile
- php - 如何配置wordpress ajax超时限制
- python - 具有服务器端证书问题的 Python Paho-mqtt 客户端
- python - 从文件中删除特定模式