如何为高需求应用程序设置node.js堆栈?

如何为高需求应用程序设置node.js堆栈?,node.js,mongodb,sails.js,mean-stack,Node.js,Mongodb,Sails.js,Mean Stack,我目前正在开发一个Node.js堆栈应用程序,有25000多人使用,我们特别使用Sails.js框架,我们得到了MongoDB 应用程序运行在一个具有30GB RAM的EC2实例上,数据库运行在EC2所在区域内基于Mongolab AWS的集群上。我们甚至有一个弹性缓存Redis实例,存储容量为1.5GB 因此,我们面临的主要和巨大的问题是延迟。当我们达到并发用户请求应用程序的高峰时,我们会收到多个超时,并且sail应用程序的RAM超过7.5GB,对API的HTTP请求需要超过15秒(这是不可接

我目前正在开发一个Node.js堆栈应用程序,有25000多人使用,我们特别使用Sails.js框架,我们得到了MongoDB 应用程序运行在一个具有30GB RAM的EC2实例上,数据库运行在EC2所在区域内基于Mongolab AWS的集群上。我们甚至有一个弹性缓存Redis实例,存储容量为1.5GB

因此,我们面临的主要和巨大的问题是延迟。当我们达到并发用户请求应用程序的高峰时,我们会收到多个超时,并且sail应用程序的RAM超过7.5GB,对API的HTTP请求需要超过15秒(这是不可接受的),甚至当收到nginx发送的502和504响应时

我可以注意到Mongo写操作是我们的主要延迟问题,但是,当出现需求高峰时,即使GET请求也需要很长时间。我无法访问生产服务器,我只有pm2提供的keymetrics监控工具(实际上非常棒)和NewRelic警报

所以,我想知道一些解决这些问题的路线图,也许应该提供更详细的信息,到目前为止,我可以说,当用户不多时,应用程序看起来是稳定的

<> P>主要的因素和设置是什么? 到目前为止,我知道我应该做什么,但我不确定细节和方法

IMHO:

  • 尽可能多地缓存
  • 延迟MongoDB写入操作
  • 具有较高写入要求的独立Mongo数据库
  • 虚拟化
  • 调整节点设置
  • 关于优化代码,我发布了另一个stackoverflow问题,其中有一个示例


    您对生产应用程序有何建议和意见?

    首先,确保您没有使用同步I/O。如果您可以在
    io.js
    上运行,则会有
    --跟踪同步io
    标志(
    iojs--跟踪同步io服务器.js
    )如果将同步代码与以下控制台警告一起使用,将发出警告:
    警告:检测到使用了同步API

    其次,找出RAM使用率如此之高的原因。如果因为大量的数据加载到内存(XML解析,大量的数据从MangGDB等返回),你应该考虑使用<代码>流< /代码>。V8垃圾收集(在
    Node.js
    /
    io.js
    中使用的谷歌JavaScript虚拟机)如果内存使用率过高,可能会导致速度减慢。更多信息:和

    第三,实验和

    最后,检查您是否使用或可以切换到
    MongoDB
    3.x。我们已经观察到,仅通过从2.x升级到3.x,就可以获得一些显著的性能提升。

    对于Mongodb,您可以使用它来查看哪些数据库有争议,每个数据库使用2.2+个锁,如果数据库具有写重工作负载,那么在Mongodb使用时,读取将受到影响

    对于node.js,您可以检查是否存在可以解释API请求延迟的任何类型的事件循环延迟

    (function getEventLoopDelay() {
        var startTime = Date.now();
        setTimeout(function() {
            console.log(Math.max(Date.now() - startTime - 1000, 0));
            getEventLoopDelay();
        }, 100);
    })();
    

    基本上大部分的要点都已经在答案中出现了。我只是总结一下

    要优化应用程序,您可以做几件主要的事情

  • 尝试将表单
    node.js
    移动到
    io.js
    它仍然有更好的性能和最新的尖端更新。(但要仔细阅读实验特征)。或者至少从
    node.js
    v10
    v12
    。有很多性能优化

  • 避免使用使用使用I/O操作或处理大量数据的同步函数

  • 从一个节点进程切换到系统

  • 检查应用程序是否存在内存泄漏。我将用于
    node.jsv12
    node.jsv10

  • 尽量避免将数据保存到全局变量

  • 使用缓存。对于应该可以全局访问的数据,您可以使用
    Redis
    Memcached
    也是一个很好的存储

  • 避免将
    async
    承诺一起使用。两个LIB都在做同样的事情。因此,无需同时使用这两种方法。(我在您的代码示例中看到了这一点)

  • async.falter
    async.parallel
    方法结合在一起,这样做是可行的。 例如,如果您需要从mongo中获取一些仅与用户相关的数据,您可以获取用户,然后并行地获取所有其他需要的数据

  • 如果您使用的是
    sails.js
    请确保它处于
    production
    模式。(我想你已经这么做了)

  • 禁用所有不需要的挂钩。在大多数情况下,
    grunt
    hook是无用的。如果应用程序中不需要
    Socket.io
    ,请使用
    .sailsrc
    文件禁用它。比如:

    { “发电机”:{ “模块”:{} }, “挂钩”:{ “咕噜”:错, “套接字”:false } }

  • 另一个可以禁用的钩子是:
    i18n
    csrf
    cors
    。但前提是你不在你的系统中使用它们

  • 禁用无用的全球化。在
    config/globals.js
    中。我假设默认情况下可以禁用
    \uuu
    异步
    服务
    。因为
    Sails.js
    使用了旧版本的
    lodash
    async
    库,新版本的性能要好得多

  • 手动将
    lodash
    async
    安装到
    Sails.js
    项目中,并使用新版本。(第11点)

  • 将结果返回给用户后,可以进行一些“写入mongo”操作。例如:您可以调用
    res.view()
    方法,该方法将在
    Model.save()之前向用户发送响应,但代码将继续使用所有变量运行,因此您可以将数据保存到mongo DB。所以用户在写操作期间不会看到延迟

  • 您可以使用队列来执行需要大量资源的操作。例如:如果y