I wrote a simple appEngine using pubsub app. When looking at the appEngine logs i saw that memory is constantly increasing and dropping and it keeps reoccuring. When i looked at the logs. I got the below error message. Basically what i am doing is, i have setup a cron task to trigger this route every minute, the express route will publish the message to pubsub. For this simple task, i am seeing memory usage consistently increasing from 89MB to 131MB and in the next upcoming trigger it fails. Please suggest me how to resolve this memory leaks.
2018-07-22 10:51:00.266 IST
Exceeded soft private memory limit of 128 MB with 130 MB after servicing 9 requests total. Consider setting a larger instance class in app.yaml.
2018-07-22 10:51:00.266 IST
After handling this request, the process that handled this request was found to be using too much memory and was terminated. This is likely to cause a new process to be used for the next request to your application. If you see this message frequently, you may have a memory leak in your application or may be using an instance with insufficient memory. Consider setting a larger instance class in app.yaml.
Below are the code sample index.js
const express = require('express');
const app = express();
const pubsub = require('./pubsub1.js');
app.get('/', (req, res) => {
res.send('Hi!');
});
app.get('/hello', (req, res) => {
var planet = req.query.planet || 'Earth';
res.send(`Hello Planet ${planet}!`);
});
app.get('/helloAppengineFROMcron', (req, res) => {
var message = req.query.date || 'no date';
//res.status(200).send(`Hello ${name || 'World'}!`);
res.send(`Hello from Express app, just triggered a pubsub messsage @ ${message}`);
console.log(`Hello from Express app, just triggered a pubsub messsage @ ${message}`);
pubsub.publishMessage('helloPubsubFROMappengine', '--> appEngine');
});
//const server = app.listen(process.env.PORT || 8080, "localhost", () => {
const server = app.listen(process.env.PORT || 8080, () => {
const host = server.address().address;
const port = server.address().port;
console.log(`Express cron http://${host}:${port}`);
});
pubsub1.js
//Program : pubsub1.js
// Imports the Google Cloud client library
const PubSub = require(`@google-cloud/pubsub`);
function getCurrentISTdt(format){
var cDT = new Date();
var currentOffset = cDT.getTimezoneOffset();
var ISTOffset = 330; // IST offset UTC +5:30
var ISTTime = new Date(cDT.getTime() + (ISTOffset + currentOffset)*60000);
var day = ISTTime.getDate() > 9 ? ISTTime.getDate() : '0'+ISTTime.getDate();
var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var month = months[cDT.getMonth()];
var mm = (ISTTime.getMonth()+1) > 9 ? (ISTTime.getMonth()+1) : '0'+(ISTTime.getMonth()+1);
var year = ISTTime.getFullYear();
var h = ISTTime.getHours() > 9 ? ISTTime.getHours() : '0'+ISTTime.getHours();
var m = ISTTime.getMinutes() > 9 ? ISTTime.getMinutes() : '0'+ISTTime.getMinutes();
var s = ISTTime.getSeconds() > 9 ? ISTTime.getSeconds() : '0'+ISTTime.getSeconds();
var cISTdt;
if(format == "yyyymmdd"){
cISTdt = year+''+mm+''+day;
}else if(format == "yyyymm"){
cISTdt = year+''+mm;
}else if(format == "yyyy"){
cISTdt = year;
}else if(format == "yyyy-mmm-dd hh:mm:ss"){
cISTdt = year+'-'+month+'-'+day+' '+h+':'+m+':'+s;
}else if(format == "dd/mm/yyyy hh:mm:ss"){
cISTdt = day+'/'+mm+'/'+year+' '+h+':'+m+':'+s;
}
else{
cISTdt = year+'/'+mm+'/'+day+' '+h+':'+m+':'+s;
}
return cISTdt;
}
function publishMessage(topicName, data) {
// [START pubsub_publish]
// [START pubsub_quickstart_publisher]
// Creates a client
const pubsub = new PubSub();
/**
* TODO(developer): Uncomment the following lines to run the sample.
*/
// const topicName = 'your-topic';
// const data = JSON.stringify({ foo: 'bar' });
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
data = data?data:' missed appEngine data ';
data = data + ' --> Pubsub';
const dataBuffer = Buffer.from(data);
pubsub
.topic(topicName)
.publisher()
.publish(dataBuffer)
.then(messageId => {
console.log(`Message triggered from pubsub() @ ${getCurrentISTdt("yyyy-mmm-dd hh:mm:ss")} - ID:${messageId} published.`);
})
.catch(err => {
console.error('ERROR:', err);
});
// [END pubsub_publish]
// [END pubsub_quickstart_publisher]
}
//publishMessage('pubsubTest1', 'Helo Testing');
module.exports = {
//functionName there : functionName here
publishMessage,
getCurrentISTdt
};
package.json
{
"name": "gae-hello",
"version": "1.0.0",
"description": "HelloWorlds GAE",
"main": "app.js",
"scripts": {
"start": "node app.js",
"deploy": "gcloud app deploy --quiet",
"test": "echo \"Error: no test specified\" && exit 1"
},
"engines": {
"node": "8.x.x"
},
"keywords": [
"express.js",
"cron",
"GAE",
"appEngine"
],
"author": "Sushanth Bobby Lloyds",
"license": "ISC",
"dependencies": {
"@google-cloud/pubsub": "^0.19.0",
"express": "^4.16.3"
}
}
You may not be experienceing a memory leak, but may just be constrained by the memory available.
The default instance class of App Engine has very low RAM (128Mo). You can try to increase the imstance class to at least
F2
:In you
app.yaml
, add the following:instance_class: F2
(Read more in the docs)