【发布时间】:2018-08-08 18:16:35
【问题描述】:
我的节点应用程序面临内存问题。进行了一些堆转储,发现内存中保存了很多 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,
}
我在应用中有几个模型。每个模型都以以下方式定义(此处仅列出其中一个模型):
models/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 秒我会收到需要插入数据库的新数据(不超过 100kbs),并且一些旧的数据库数据也会根据这些新数据进行更新(似乎相当直接的数据库操作.. .读取、操作和更新回来)。
从 index.js 中,我生成了 2 个子进程,它们负责处理这些新数据并根据业务逻辑更新数据库。当使用事件侦听器在 index.js 中接收到新数据时,我将其发送到子进程 1 以插入/更新数据库。子进程 2 在 10 秒计时器上运行以读取此更新的数据,然后对数据库进行一些进一步的更新。
在我的本地 macbook pro 上运行它是没有问题的(正在使用的记录堆内存永远不会超过 40-50mb)。当我在 DO Ubuntu 16.04 服务器(4GB /2 CPU)上加载它时,我遇到了内存问题。子进程在达到进程的内存阈值(~1.5gb)后退出,这对我来说似乎很奇怪。 我也尝试使用 docker 容器来执行此操作并看到相同的结果。在 mac 上它运行没有问题,但在服务器上它正在消耗内存。 生成堆转储显示堆中有很多 mongo 对象。
我需要一些帮助来理解我在这里做错了什么以及 mongo 在服务器上占用这么多内存的问题是什么。
【问题讨论】:
标签: node.js mongodb mongoose memory-leaks