GAE - Nodejs - 一个简单的 pubsub 应用程序的内存泄漏 - 超过了软私有内存限制

Posted

技术标签:

【中文标题】GAE - Nodejs - 一个简单的 pubsub 应用程序的内存泄漏 - 超过了软私有内存限制【英文标题】:GAE - Nodejs - Memory leak for a simple pubsub app - Exceeded soft private memory limit 【发布时间】:2018-12-29 22:39:48 【问题描述】:

我使用 pubsub 应用程序编写了一个简单的 appEngine。在查看 appEngine 日志时,我看到内存在不断增加和减少,并且不断重复。当我查看日志时。我收到以下错误消息。基本上我正在做的是,我已经设置了一个 cron 任务来每分钟触发这个路由,快速路由会将消息发布到 pubsub。对于这个简单的任务,我看到内存使用量持续从 89MB 增加到 131MB,并且在下一个即将到来的触发器中它失败了。请建议我如何解决此内存泄漏。

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.

以下是代码示例 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"
  

【问题讨论】:

after servicing 9 requests total - 恕我直言,9 个请求不足以建立模式。我首先尝试使用更高的实例类,以检查它是否确实存在泄漏。在我的情况下(python,tho'),这个类对于我的应用程序来说太小了(垃圾收集器没有机会运行),升级类解决了这个问题。查看相关***.com/questions/35189446/… 【参考方案1】:

您可能没有遇到内存泄漏,但可能只是受到可用内存的限制。

App Engine 的默认实例类具有非常低的 RAM (128Mo)。您可以尝试将实例类增加到至少F2

app.yaml 中添加以下内容:instance_class: F2(在the docs 中阅读更多内容)

【讨论】:

以上是关于GAE - Nodejs - 一个简单的 pubsub 应用程序的内存泄漏 - 超过了软私有内存限制的主要内容,如果未能解决你的问题,请参考以下文章

试图让基本的 Nodejs 示例在 GAE 上工作

从 Google Pub/Sub 调用 Google App Engine 端点

Redis sub/pub 和 php/nodejs

NodeJS:处理突然的云 Pub/Sub 删除

Nodejs 在 pub/sub 中从客户端发布

简单的 GAE Java JSON REST 服务器