【问题标题】:Load Balancing with Node and Heroku使用 Node 和 Heroku 进行负载平衡
【发布时间】:2015-09-24 09:17:47
【问题描述】:

我有一个网络应用程序,它接受来自 ios 应用程序的 api 请求。我的 Web 应用程序使用他们的免费 dyno 托管在 Heroku 上,每个请求能够处理 512 mb 的数据。因为节点是一个单线程应用程序,一旦我们开始从 ios 端获得更高级别的流量到 Web 服务器,这将是一个问题。我也不是世界上最富有的人,所以我想知道创建另一个免费的 heroku 应用程序并使用循环方法来平衡从 ios 应用程序收到的负载是否明智?

我只需要指出正确的方向。垂直扩展在财务上并不是真正的选择。

【问题讨论】:

    标签: node.js heroku load-balancing


    【解决方案1】:

    我是 Heroku 的 Node.js 平台所有者。

    您可能正在进行一些过早的优化。 Node.js 在我们最小的 1X 大小(512MB RAM)上,每分钟可以处理数百个同时连接和数千个请求。

    如果您的 iOS 应用一直在发挥最大作用,那么可能是时候考虑获利了!

    【讨论】:

    • 所以你认为我在此期间应该会没事的?我几乎没有那么多要求,而且可能不会很快。我只是想计划并做好准备
    【解决方案2】:

    正如 Daniel 所说,这违反了 Heroku 规则。话虽如此,可能还有其他服务可以让您这样做。 解决此问题的一种方法是将集群模块与ZeroMQ 一起使用(您需要在使用该模块之前安装 ZeroMQ - 请参阅module description)。

    var cluster = require('cluster');
    var zmq = require('zmq');
    
    var ROUTER_SOCKET = 'tcp://127.0.0.1:5555';
    var DEALER_SOCKET = 'tcp://127.0.0.1:7777';
    
    if (cluster.isMaster) {
      // this is the main process - create Router and Dealer sockets
      var router = zmq.socket('router').bind(ROUTER_SOCKET);
      var dealer = zmq.socket('dealer').bind(DEALER_SOCKET);
    
      // forward messages between router and dealer
      router.on('message', function() {
        var frames = Array.prototype.slice.cal(arguments);
        dealer.send(frames);
      });
    
      dealer.on('message', function() {
        var frames = Array.prototype.slice.cal(arguments);
        router.send(frames);
      });
    
      // listen for workers processes to come online
      cluster.on('online', function() {
        // do something with a new worker, maybe keep an array of workers
      });
    
      // fork worker processes
      for (var i = 0, i < 100; i++) {
        cluster.fork();
      }
    } else {
      // worker process - connect to Dealer
      let responder = zmq.socket('rep').connect(DEALER_SOCKET);
    
      responder.on('message', function(data) {
        // do something with incomming data
      })
    }
    

    这只是为您指明正确的方向。如果您考虑一下,您可以创建一个带有参数的脚本,该参数将告诉它是主进程还是工作进程。然后在主服务器上按原样运行它,并在其他服务器上使用工人标志运行它,这将强制它连接到主经销商。

    现在您的主应用需要将请求发送到路由器,然后再转发到工作进程:

    var zmq = require('zmq');
    var requester = zmq.socket('req');
    
    var ROUTER_SOCKET = 'tcp://127.0.0.1:5555';
    
    // handle replies - for example completion status from the worker processes
    requester.on('message', function(data) {
      // do something with the replay
    });
    
    requester.connect(ROUTER_SOCKET);
    
    // send requests to the router
    requester.send({
      // some object describing the task
    });
    

    【讨论】:

    • 这绝对是我倾向于的。谢谢!
    【解决方案3】:

    首先,正如其他回复所指出的那样,运行应用程序的两个副本以避免 Heroku 的限制违反了他们的 ToS,这可能不是一个好主意。

    不过,有一些好消息。对于初学者(来自Heroku's docs):

    如果内存使用情况如下,测功机管理器将重新启动您的测功机并记录 R15 错误:

    • 免费、业余爱好或标准 1x dyno 达到 2.5GB,是其配额的五倍。

    据我了解,尽管您的测功机有 512mb 的 实际 RAM,但它会在实际重新启动之前换出 5 倍。所以你可以超过 512mb(只要你愿意为交换到磁盘付出性能损失,这可能很严重)。

    除此之外,Heroku 按秒计费,并允许您根据需要向上和向下扩展您的测功机编队。通过点击 Heroku API 在您自己的应用程序中执行此操作相当容易 - 我看到您已使用 NodeJS 标记了它,因此您可能想查看:

    这两个模块都允许您扩大和缩小您的 dyno 的形成 - 使用简单的启发式方法(例如,始终运行一个备用的 1X dyno),您可以在处理请求时增加容量,然后摆脱api 请求未运行时的备用容量。鉴于您按秒计费,这最终可能会非常便宜。 1X 测功机的运行时间约为 5 美分 /小时。如果您最终每天运行额外的测功机几个小时,这对您来说是非常非常小的成本。

    最后:还有 3rd 方服务,例如 AdeptHirefire(来自 Google 的两个随机示例,我相信还有更多)可以让您在某种程度上实现自动化,但我没有对他们有任何经验。

    【讨论】:

      【解决方案4】:

      你当然可以,我的意思是,以编程方式——但这会绕过Heroku's TOS

      4.4 您不得开发多个应用程序来模拟或充当单个应用程序,或以其他方式访问 Heroku 服务以避免产生费用。

      现在,我不确定:

      由于节点是单线程应用程序,一旦我们开始从 ios 端获得更高级别的流量到 Web 服务器,这将是一个问题。

      有一些线程在讨论这个问题,并给出了一些有趣的答案:

      Clustering Node JS in Heavy Traffic Production Environment

      How to decide when to use Node.js?

      此外,他们还链接到该视频,介绍 Node.js,其中谈到了一些基准:

      Introduction of Node JS by Ryan Dahl

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-21
        • 1970-01-01
        • 1970-01-01
        • 2018-03-12
        • 2019-10-20
        • 2012-06-04
        • 1970-01-01
        相关资源
        最近更新 更多