【问题标题】:Memory issue with mongo in node节点中mongo的内存问题
【发布时间】: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


    【解决方案1】:

    因此,TrackerHistory 集合的建模方式存在很大问题。 TrackerHistory 有一个数组,每次必须将一个新对象添加到数组中时,整个 TrackerHistory 对象都被加载到内存中,并且在更新实时数据的给定频率下,内存膨胀的速度比 gc 快' d.

    通过删除新集合中的跟踪器数组并添加对 TrackerHistory 的外键引用来修复它。

    帮助我识别此问题的参考文章。

    https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 2018-12-29
      • 1970-01-01
      相关资源
      最近更新 更多