我的节点应用程序面临内存问题。拿了一些堆转储并看到很多mongo对象被保存在内存中,导致节点应用程序耗尽内存。
我的应用程序有以下设置。
MongoDB 3.4.13
Mongoose 4.11.10(尝试过4.13.11和5.0.7)
节点8.9.4
config.js
const clientUID = require('./env').clientUID;
module.exports = {
// Secret key for JWT signing and encryption
secret: 'mysecret',
// Database connection information
database: `mongodb://localhost:27017/app_${clientUID}`,
// Setting port for server
port: process.env.PORT || 3000,
}
我在应用程序中有几个模型。每个模型都按以下方式定义(仅列出其中一个模型):
模型/ card.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CardSchema = new Schema({
name: {
type: String,
unique: true,
required: true
},
macId: {
type: String,
unique: true,
required: true
},
cardTypeId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'CardType',
required: true
},
},
{
timestamps: true
});
module.exports = mongoose.model('Card', CardSchema);
在应用程序中,我需要模型并执行以下操作:
const Card = require('./models/card');
...require other models
const config = require('./config');
mongoose.connect(config.database);
function fetchCardByMacId(macId) {
return Card.findOne({ macId }).lean().exec();
}
function updateTrackerByMacId(macId, x, y, nodeId) {
const data = {x, y, lastNodeId: nodeId};
fetchCardByMacId(macId)
.then(card => {
Tracker.findOneAndUpdate({ cardId: card._id }, data, { upsert: true, new: true }).exec((error, tracker) => {
if (error) {
return console.log('update tracker error', error);
}
TrackerHistory.findOne({ trackerId: tracker._id }).exec((err, trackerHistory) => {
if (err) {
return console.log('fetch trackerHistory error', err);
}
if (trackerHistory) {
trackerHistory.trackers.push({ x, y, timestamp: moment().format(), nodeId });
TrackerHistory.findOneAndUpdate({_id: trackerHistory._id},trackerHistory,(er, trackerHis) => {
if (er) {
return console.log('trackerHistory change update error', er);
}
})
} else {
const trackerHistoryNew = new TrackerHistory({
trackerId: tracker._id,
trackers: [{ x, y, timestamp: moment().format(), nodeId }]
});
trackerHistoryNew.save((er, trackerHis) => {
if (er) {
return console.log('trackerHistory create error', er);
}
});
}
});
});
}).catch(error => {
console.log('updateTrackerByMacId error', error);
});
}
像这样,还有许多其他功能可以读取和更新数据。
我每5秒钟就会收到需要插入数据库的新数据(不超过几百kbs),并且一些旧的数据库数据也会根据这些新数据进行更新(看起来像是相当简单的db操作... .read,操作和更新)。
我从index.js中生成了2个子进程,这些进程负责处理这些新数据并根据业务逻辑更新数据库。当使用事件侦听器在index.js中接收到新数据时,我将其发送到子进程1以插入/更新数据库。子进程2在10s计时器上运行以读取此更新数据,然后对数据库进行进一步更新。
在我的本地macbook pro上运行它是没有问题的(使用的日志堆内存永远不会超过40-50mb)。当我将它加载到DO Ubuntu 16.04服务器(4GB / 2 CPU)时,我面临内存问题。在达到进程的内存阈值(~1.5gb)后,子进程正在退出,这对我来说似乎很奇怪。 我还尝试使用docker容器执行此操作并查看相同的结果。在Mac上运行没有问题,但在服务器上它正在吃掉内存。 生成heapdumps会在堆中显示很多mongo对象。
我想帮助理解我在这里做错了什么,以及mongo在服务器上占用这么多内存的问题是什么。
答案 0 :(得分:0)
因此TrackerHistory集合的建模方式存在很大问题。 TrackerHistory有一个数组,每次必须将一个新对象添加到数组中时,整个TrackerHistory对象都被加载到内存中,并且在更新实时数据的给定频率下,内存膨胀的速度比gc&#更快。 39; d
通过删除新集合中的跟踪器数组并向TrackerHistory添加外键引用来修复它。
帮助我确定此问题的参考文章。
https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1