Load Balancing with Node and Heroku
我有一个接受iOS应用程序的API请求的Web应用程序。我的网络应用程序在Heroku上使用免费的Dyno托管,它可以处理每个请求512MB的数据。因为节点是单线程应用程序,所以一旦我们开始从iOS端获得更高级别的流量到Web服务器,这将是一个问题。我也不是世界上最富有的人,所以我想知道创建另一个免费的Heroku应用程序并使用循环方法来平衡从iOS应用程序收到的负载是否明智?
我只需要指出正确的方向。在财政上,垂直伸缩并不是一个真正的选择。
我是Heroku的node.js平台所有者。
您可能正在进行一些过早的优化。在我们最小的1X大小(512MBRAM)上,node.js可以每分钟处理数百个同时连接和数千个请求。
如果你的iOS应用程序一直在最大限度地利用这一点,那么是时候考虑货币化了!
正如丹尼尔所说,这违反了英雄的规则。尽管如此,可能还有其他的服务可以让你做到这一点。解决这个问题的一种方法是使用带有zeromq的集群模块(在使用模块之前需要安装zeromq—请参阅模块描述)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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 }) } |
这只是为了给你指明正确的方向。如果您考虑一下,您可以用一个参数创建一个脚本,该参数将告诉它是主进程还是工作进程。然后在主服务器上按原样运行它,在其他服务器上使用worker标志运行它,这将强制它连接到主经销商。
现在,您的主应用程序需要将请求发送到路由器,路由器稍后将转发到工作进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 }); |
因此,首先,正如其他回复所指出的,运行两个应用程序副本以避免Heroku的限制违反了他们的TOS,这可能不是一个好主意。
然而,有一些好消息。对于初学者(来自Heroku的文档):
The dyno manager will restart your dyno and log an R15 error if the memory usage of a:
- free, hobby or standard-1x dyno reaches 2.5GB, five times its quota.
据我所知,尽管您的Dyno有512MB的实际RAM,但在实际重新启动之前,它将换成5倍的内存。因此,您可以超过512MB(只要您愿意支付交换到磁盘的性能损失,这可能很严重)。
除此之外,Heroku会在第二个阶段进行计费,并允许你根据需要上下调整你的Dyno阵型。通过点击Heroku API,在你自己的应用程序中很容易做到这一点——我看到你已经用nodejs标记了这一点,所以你可能想看看:
- Heroku的节点客户端
- 非常简单但仍能正常工作的toots/node heroku模块
这两个模块都允许您放大和缩小Dyno的组成——通过一个简单的启发式(比如,总是有一个备用的1X Dyno运行),您可以在处理请求时增加容量,在API请求不运行时去掉备用容量。考虑到你是按秒计费的,这最终可能是非常便宜的;1X达诺系统的运行时间大约是每小时5美分。如果你最终一天要运行几个小时的额外的Dynos,对你来说这是一个非常非常小的成本。
最后:还有第三方服务,如Adept和HireFire(两个随机的例子来自Google,我相信还有更多)可以让你在某种程度上实现自动化,但我对它们没有任何经验。
你当然可以,我的意思是,编程-但那将绕过希罗库的任务:
4.4 You may not develop multiple Applications to simulate or act as a single Application or otherwise access the Heroku Services in a manner intended to avoid incurring fees.
现在,我不确定:
Because node is a single threaded application this will be a problem once we start getting higher levels of traffic from the ios end to the web server.
有一些主题讨论这个问题,并给出一些有趣的答案:
大流量生产环境下的集群节点JS
如何决定何时使用node.js?
此外,他们还链接到这段视频,介绍了node.js,其中介绍了一些基准测试:
Ryan Dahl介绍的节点JS