【发布时间】:2017-05-10 17:35:19
【问题描述】:
我遇到了 setInterval() 问题,导致我的 Node.js 应用程序出现内存泄漏。该应用程序很简单:它每半小时唤醒一次,查看 MongoDB 表以查看是否有任何工作要做(大多数情况下没有),然后向找到的符合条件的记录发送一封电子邮件。随着时间的推移(几天),内存从 100MB 增加到超过 1GB。
我尝试将变量移到 setInteveral 之外以获得 GC,但没有运气。我错过了什么吗?
我正在使用 New Relic 来监控交易,但在我添加此工具之前,此问题仍然存在。
const transactionName = 'email-scheduler';
let invokeTransaction = newrelic.createBackgroundTransaction(transactionName,
function () {
sendEmail(function (error) {
log.info("Job completed; ending transaction.");
newrelic.endTransaction();
});
}); //must be outside of setInterval to be GC'd
if (RUN_SCHEDULER) {
setInterval(invokeTransaction, JOB_INTERVAL_MINUTES * 1000 * 60);
}
function sendEmail(callback) {
log.info('Scheduler woke up to send emails (set to send every ' + JOB_INTERVAL_MINUTES + ' minutes)');
mongo.findUsersSince(180, function (err, result) {
if (err) {
log.error("Welcome emails could not be sent: " + err);
callback(err);
}
else if (result && result instanceof Array) {
api.sendEmail(resutlt);
} else {
callback(null);
}
});
}
当我使用像 Cron 这样的包而不是 setInterval() 时,这是替代版本。遇到同样的问题:
function sendEmail(callback) {
log.info('Scheduler woke up to send emails (set to send every ' + JOB_INTERVAL_MINUTES + ' minutes)');
try {
new CronJob('0 */' + JOB_INTERVAL_MINUTES + ' * * * *', function () {
log.info('Scheduler woke up to send emails (set to send every ' + JOB_INTERVAL_MINUTES + ' minutes)');
mongo.findUsersSince(OKTA_WAIT_MINUTES, function (err, result) {
if (err) {
log.error("Welcome emails could not be sent: " + err);
callback(err);
}
else if (result && result instanceof Array) {
api.sendEmail(resutlt);
} else {
callback(null);
}
});
}, function () {
log.info('Scheduler completed job.');
}, RUN_SCHEDULER, "America/Los_Angeles");
} catch (ex) {
log.error("cron job pattern not valid");
}
}
【问题讨论】:
-
很好奇你为什么要这样做:
let invokeTransaction = invokeTransaction = ...这甚至不适合我。 -
错字...已更正。
-
为什么
invokeTransaction会被 GC 处理?它在全局空间中,永远不会被覆盖......我认为将整个逻辑放在容器函数中会更好,只使用局部变量 - 这将使 GC 更有可能清除它们(假设不长 - life 变量保持绑定范围)。
标签: javascript node.js memory-leaks