You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS+Express+MongoDB内存泄漏问题排查求助

内存泄漏问题诊断与修复方案

你的服务内存泄漏并非单纯堆内存不足导致,核心问题出在定时任务的并发查询堆积、旧数据引用未及时回收,以及MongoDB查询的资源占用上,以下是针对性修复方案:

1. 给定时任务加并发锁,避免重复查询

如果前一次MongoDB查询还未完成,下一个定时任务就启动,会导致内存中同时存在多份查询结果,快速耗尽内存。加锁可以避免这种情况:

import { tokenModel } from '../../dbmodels/models.js';

let data = null;
let isFetching = false; // 并发锁

setInterval(async () => {
    if (isFetching) return; // 正在查询则跳过本次任务
    isFetching = true;
    try {
        data = null; // 先清空旧数据,帮助GC回收
        data = await tokenModel.find({
            $or: [
                { "currentRanks.minuteTokenRank": {$lt: 51} },
                { "currentRanks.fiveMinuteTokenRank": {$lt: 51} },
                { "currentRanks.fifteenMinuteTokenRank": {$lt: 51} },
                { "currentRanks.thirtyMinuteTokenRank": {$lt: 51} },
                { "currentRanks.hourlyTokenRank": {$lt: 51} },
                { "currentRanks.dailyTokenRank": {$lt: 51} },
                { "currentRanks.weeklyTokenRank": {$lt: 51} }
            ]
        }).lean();
    } catch (error) {
        console.error(error);
    } finally {
        isFetching = false; // 无论成败都释放锁
    }
}, 45000);

2. 优化MongoDB查询,减少内存占用

当前查询返回整个文档,若数据量大会持续占用内存。用select()只返回业务需要的字段,同时给查询字段加索引提升效率:

代码修改:

// 查询时只返回需要的字段,替换成你实际用到的字段
data = await tokenModel.find({/* 原查询条件 */})
    .lean()
    .select('currentRanks name id'); // 示例字段,按需调整

给MongoDB加索引:

在你的Model定义中添加索引,加快查询速度,减少查询过程中的内存消耗:

// 在tokenModel的Schema定义中添加
tokenSchema.index({ "currentRanks.minuteTokenRank": 1 });
tokenSchema.index({ "currentRanks.fiveMinuteTokenRank": 1 });
// 其他rank字段按需添加单字段索引,或建立复合索引

3. 修复接口代码的冗余逻辑

原接口中dataRes = data;后设置dataRes = null完全无效,因为dataRes是局部变量,不会影响顶层data的引用,直接简化接口逻辑:

export async function main(req, res) {
    try {
        if (!data) {
            return res.status(503).json({ message: '数据加载中,请稍后再试' });
        }
        res.status(200).json(data);
    } catch (err) {
        res.status(500).json({ message: err.message });
        console.error('接口报错:', err.message);
    }
}

4. 优化Mongoose连接配置

在server.js中给Mongoose连接添加连接池限制,避免过多连接占用内存:

// 修改连接代码
connect(process.env.DB_URL, {
    poolSize: 10, // 限制连接池大小
    maxPoolSize: 10,
    connectTimeoutMS: 30000,
});

5. 添加内存监控,确认修复效果

定时打印内存使用情况,验证泄漏是否解决:

// 在apis.js或server.js中添加
setInterval(() => {
    const { heapUsed } = process.memoryUsage();
    console.log(`当前堆内存占用: ${(heapUsed / 1024 / 1024).toFixed(2)} MB`);
}, 60000); // 每分钟打印一次

通过以上调整,应该能解决内存泄漏问题。核心是避免并发查询堆积,减少不必要的数据加载,帮助垃圾回收机制及时释放内存。

内容的提问来源于stack exchange,提问作者plat_winz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:20:07