Sendgrid-nodejs: 从sendgrid升级到@ sendgrid / mail后,内存使用量很大。

创建于 2018-04-12  ·  19评论  ·  资料来源: sendgrid/sendgrid-nodejs

发行摘要

由于sendgrid已过时,我们决定尝试@ sendgrid / mail

我们使用的已弃用的软件包没有问题,但是一旦更换了它,我们就开始从服务器内存不足中获取错误。 重要的是要提到电子邮件已经发送但服务器完全崩溃。

注意:我们暂时正在还原,但我想报告。

升级后错误:

2018-04-12T19:24:02 heroku[web.1]: Process running mem=1111M(217.0%)
2018-04-12T19:24:02 heroku[web.1]: Error R15 (Memory quota vastly exceeded)
2018-04-12T19:24:02 heroku[web.1]: Stopping process with SIGKILL
2018-04-12T19:24:02 heroku[web.1]: Process exited with status 137
2018-04-12T19:24:02 heroku[web.1]: State changed from up to crashed

重现步骤

  1. npm uninstall sendgrid
  2. npm install --save @sendgrid/mail
  3. 替换代码:

之前:

const router = require("express").Router();
const sg = require("sendgrid")(process.env.SENDGRID_API_KEY);

router.post("/email-something", (req, res) => {

  // ... some constants and validations ...

  const request = sg.emptyRequest({
    method: "POST",
    path: "/v3/mail/send",
    body: {
      personalizations: [{
        to: [{ email: process.env.FORWARDING_EMAIL }],
        subject: "[SOMETHING] Request from..."
      }],
      from: { email: "[email protected]" },
      content: [{
        type: "text/plain",
        value: "add all info here..."
      }]
    }
  });

  sg.API(request)
    .then(response => {
      res.status(200).json({
        success: true
      });
    })
    .catch(error => {
      res.status(500).json({
        success: false,
        message: "There was an error sending the email."
      });
    });
});

后:

const router = require("express").Router();
const sgMail = require("@sendgrid/mail");

sgMail.setApiKey(process.env.SENDGRID_API_KEY);

router.post("/email-something", (req, res) => {

  // ... some constants and validations ...

  const emails = [
    { // REQUEST
      to: process.env.FORWARDING_EMAIL,
      from: "[email protected]",
      subject: "[SOMETHING] Request from...",
      text: "add all info here..."
    }
  ];

  sgMail
    .send(emails)
    .then(response => {
      res.status(200).json({
        success: true
      });
    })
    .catch(error => {
      res.status(500).json({
        success: false,
        message: "There was an error sending the email."
      });
    });
});

技术细节:

我们正在使用expressjs在Heroku中运行一个nodejs服务器。 创建此小型服务器的唯一目的是将电子邮件发送到特定帐户,换句话说,它是完全隔离的,没有其他技术干扰。

  • “ sendgrid”:“ ^ 5.2.3” (已删除软件包)
  • “ @ sendgrid / mail”:“ ^ 6.2.1” (添加软件包)
  • “表达”:“ ^ 4.16.3”
  • 节点:v6.9.5
unknown or a help wanted question

最有用的评论

好消息@pgarciacamou @thinkingserious ,我已经将其范围缩小了,事实证明这不是由sendgrid邮件包引起的。

实际上,内存问题来自heroku-logger ,它试图记录成功响应。

我怀疑由于响应对象中的循环数据,这在记录器中是一个问题:

image

我建议在那里提出一个问题或避免记录响应对象,因为它是一个非常大且复杂的对象。

您可以使用我的仓库版本号https://github.com/adamreisnz/sendgrid-memory-issue-677进行测试

我剥离了很多东西,包括模板引擎来尝试缩小范围,但是最后,如果您将logger.info("sendgrid", response);替换为简单的console.log ,则可以复制它。

现在,希望我能解决我自己的内存问题:)

所有19条评论

我再次降级,这是升级之前和升级过程中以及降级之后的一些视觉效果。

您可以看到:

  1. 内存峰值,然后崩溃。
  2. 使用新软件包后,内存从平均4.5%跃升至+ 200%。
  3. 不推荐使用的库的响应时间更短,并且不会引起内存高峰。

screen shot 2018-04-12 at 4 27 00 pm

希望对您有所帮助,如果您想了解更多信息,请告诉我。

你好@pgarciacamou

感谢您报告此@pgarciacamou!

该服务器每分钟或每小时大约处理多少个请求?

最诚挚的问候,

埃尔默

cc @adamreisnz

@thinkingserious

该服务器每分钟或每小时大约处理多少个请求?

如果您要问我,现在正在处理多少个? 在繁忙的一天中,从1到100的任何地方请求一个小时。

但是,如果您问我,它可以处理多少个? 好吧,我不确定该问题的答案,我必须对服务器进行负载测试,但我们使用的是在Heroku中运行在单个dyno上的NodeJS,并引用了Heroku:

单个dyno每秒可以处理数千个请求,但是性能很大程度上取决于您使用的语言和框架。
...
Java,Unicorn,EventMachine和Node.js等多线程或事件驱动的环境可以处理许多并发请求。 对应用程序进行负载测试是确定请求吞吐量的唯一现实方法。
-https : //devcenter.heroku.com/articles/dynos#dynos -and-requests

我不确定这会如何影响。

大家好,我自己也在自己的Node项目中使用了新的邮件程序包,该程序也在Heroku上运行,但是到目前为止,我还没有遇到任何内存问题。

Heroku的性能数据看起来确实很奇怪。 即使存在内存问题,我也不希望它产生如此大的影响。 我们发送大量邮件,有时一次(顺序)发送数百封邮件,并且没有经历30秒钟的请求时间或与内存相关的崩溃。

@pgarciacamou Heroku应用程序在什么堆栈上运行? 您是否已将其升级到最新版本? 您是否考虑过在Node 8上运行?

@thinkingserious您的团队中有人在分析内存泄漏/使用方面有经验吗? 我目前正在采取行动,下一两周将无法进行调查。

@adamreisnz

大家好,我自己也在自己的Node项目中使用了新的邮件程序包,该程序也在Heroku上运行,但是到目前为止,我还没有遇到任何内存问题。

非常高兴知道,谢谢!

你能告诉我吗:

  1. 你在用快递吗? 如果是这样,什么版本?
  2. 节点版本
  3. @ sendgrid /邮件版本
  4. 您正在使用的heroku测功机类型

您的Heroku应用程序在什么堆栈上运行? 您是否已将其升级到最新版本? 您是否考虑过在Node 8上运行?

如前所述,我们正在使用node和express在单个爱好dyno上运行,package.json中的依赖项如下所示:

  "dependencies": {
    "express": "^4.16.3",
    "helmet": "^3.12.0",
    "sendgrid": "^5.2.3"
  }

我将尝试升级节点版本,并在星期一再次重试此步骤,感谢您的创意!

如前所述,我们正在使用node和express在单个爱好dyno上运行,package.json中的依赖项看起来像这样

不,我的意思是底层的linux版本,在您的应用程序的设置页面上列为“堆栈”:

image

我们使用的是基于Ubuntu 16.04的heroku-16 。 您可能处于较旧的堆栈中,因为您需要手动启动升级过程。

我们在Node 8.10.0上运行,是的,同时使用express ,版本^ 4.16.3和@sendgrid/mail版本^ 6.2.1。

我们目前也正在使用爱好测功机。

让我知道您最终会发现什么,是的,可以进行升级Node以及可能的Heroku堆栈👍

在设置页面上列为“堆栈”

screen shot 2018-04-18 at 10 23 11 am

如果今天发现任何行为问题,我将在今天或明天将节点升级到最新的稳定版本,然后降级到8.10并重新测试。

我会及时向大家发布。

由于我们正在将该版本用于其他存储库,因此我们已升级到节点v9.8.0。 运行测试后,我们注意到了相同的行为(已发送电子邮件,但服务器崩溃或接近崩溃)。

screen shot 2018-04-19 at 2 33 34 pm

我们遵循的步骤:

$ npm uninstall sendgrid
$ npm install @sendgrid/mail

$ nvm install v9.8.0
v9.8.0 is already installed.
Now using node v9.8.0 (npm v5.8.0)

# we updated .nvmrc to v9.8.0 and package.json engines to "node": "9.8.0"
# then deployed to heroku...

这是PR的一些清理屏幕截图(我不得不从公司中删除评论,等等。)

screen shot 2018-04-19 at 2 40 44 pm
screen shot 2018-04-19 at 2 41 18 pm

我已将此添加到我的积压中以进行更深入的研究。 目前,这可能会有所帮助。 感谢您抽出宝贵时间提供所有详细信息!

感谢@thinkingserious和@adamreisnz!

@pgarciacamou是否可以共享应用程序的完整代码示例(如果不是专有的),或者以其他方式设置存储库,并在将其部署到Heroku时出现可复制的问题? 这将允许我进一步分析。

@adamreisnz我无法从应用程序中共享代码(私人回购和有关公司的其他信息),但是下周将创建一个几乎完美克隆的临时回购。

我决定立即执行此操作,这是存储库: https :

一些评论:

首先也是最重要的是,如果您发现任何看起来像是私人的东西,请尽快告诉我。

  1. 阅读自述文件
  2. 可能到处都有小错误/错别字,因为我不进行测试就尽可能快地清理了它。
  3. 有3次提交:

让我知道它是否有任何帮助。

对此非常感谢。 这个星期和下一个星期我都比较忙,但是有空的时候我会尽量研究一下。

昨天我自己遇到了内存问题,但是,它似乎源于bcrypt升级到2.x。 但是,它促使我去调查这个问题,看看是否可以深入研究它。 我将在本周末进行调查,如果发现任何问题,请报告。

好消息@pgarciacamou @thinkingserious ,我已经将其范围缩小了,事实证明这不是由sendgrid邮件包引起的。

实际上,内存问题来自heroku-logger ,它试图记录成功响应。

我怀疑由于响应对象中的循环数据,这在记录器中是一个问题:

image

我建议在那里提出一个问题或避免记录响应对象,因为它是一个非常大且复杂的对象。

您可以使用我的仓库版本号https://github.com/adamreisnz/sendgrid-memory-issue-677进行测试

我剥离了很多东西,包括模板引擎来尝试缩小范围,但是最后,如果您将logger.info("sendgrid", response);替换为简单的console.log ,则可以复制它。

现在,希望我能解决我自己的内存问题:)

首先, @ adamreisnz非常感谢您花费的时间!

我一定会看一下,如果发现这就是问题,将在heroku-logger创建一个问题。 对于我来说仍然很奇怪,该问题仅在升级sendgrid时发生。

无论如何,由于您遇到内存问题(尽管可能不相关),所以我没有关闭此问题,请随时关闭此问题。

@pgarciacamou没问题,我认为在您升级后发生这种情况的原因是,新的sendgrid库从request返回整个原始响应对象,而且我相信以前的库没有,或者返回了简化的库响应。 当前响应很大,并且包含循环引用,从而导致记录器失败。

那我让@thinkingserious结束这个问题! 👍

@adamreisnz很有道理。 我可以用lodash( _.pick )过滤信息,而不是记录所有内容。

再次感谢!

此页面是否有帮助?
0 / 5 - 0 等级