Ich habe ein Problem mit setInterval()
verursacht einen Speicherverlust in meiner Node.js-Anwendung. Die App ist einfach: Sie wacht jede halbe Stunde auf, sucht in einer MongoDB-Tabelle nach, ob etwas zu tun ist (meistens nicht), und sendet dann eine E-Mail an die gefundenen Datensätze, die das Kriterium erfüllen. Im Laufe der Zeit (ein paar Tage) geht der Speicher von 100 MB auf über 1 GB.Speicherverlust mit setInterval in einem Node.js-Prozess ausgeführt
Ich habe versucht, die Variablen außerhalb der setInteveral zu bewegen GC'd aber kein Glück. Fehle ich etwas?
Ich verwende New Relic, um die Transaktion zu überwachen, aber dieses Problem beharrte, bevor ich diese Instrumentierung hinzufüge.
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);
}
});
}
Hier ist die alternative Version, wenn ich ein Paket wie Cron statt setInterval() verwenden. Leiden aus dem gleichen Problem:
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");
}
}
neugierig, warum Sie das tun: 'Lassen Sie invokeTransaction = invokeTransaction = ...' Das kompiliert nicht für mich. – flash
Typo ... korrigiert. – occasl
Warum sollte 'InvokeTransaction' jemals gecodiert werden?Es ist im globalen Raum, nie überschrieben ... Ich würde annehmen, dass es besser wäre, die gesamte Logik in eine Container-Funktion zu stellen, die nur lokale Variablen verwendet - das würde es wahrscheinlicher machen, dass der GC sie löscht (vorausgesetzt, Lebensvariable hält sich an den verbindlichen Geltungsbereich). – Myst