使用 Node 和 Heroku 进行负载均衡
Load Balancing with Node and Heroku
我有一个网络应用程序可以接受来自 ios 应用程序的 api 请求。我的网络应用程序托管在 Heroku 上,使用他们的免费测功机,每个请求能够处理 512 MB 的数据。因为节点是一个单线程应用程序,所以一旦我们开始从 ios 端到 Web 服务器获得更高级别的流量,这将是一个问题。我也不是世界上最富有的人,所以我想知道创建另一个免费的 heroku 应用程序并使用循环法来平衡从 ios 应用程序收到的负载是否明智?
我只需要指出正确的方向。垂直扩展在财务上并不是一个真正的选择。
你当然可以,我的意思是,以编程方式 - 但那会绕过 Heroku's TOS:
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.
有一些线程在讨论这个问题,并给出了一些有趣的答案:
Clustering Node JS in Heavy Traffic Production Environment
How to decide when to use Node.js?
此外,他们 link 观看了该视频,介绍了 Node.js,其中讨论了一些基准测试:
正如 Daniel 所提到的,它违反了 Heroku 规则。话虽如此,可能还有其他服务可以让您这样做。
解决此问题的一种方法是将集群模块与 ZeroMQ (you need to have ZeroMQ installed before using the module - see 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
})
}
这只是为您指明正确的方向。如果您考虑一下,您可以创建一个带有参数的脚本,该参数将告诉它它是主进程还是工作进程。然后在主服务器上 运行 它是原样,在其他服务器上 运行 它使用 worker 标志,这将强制它连接到主要经销商。
现在您的主应用需要将请求发送到路由器,稍后将转发到工作进程:
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 的限制违反了他们的服务条款,这可能不是一个好主意。
不过,也有一些好消息。对于初学者(来自 Heroku's docs):
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.
据我了解,尽管您的测功机有 512mb 的 实际 RAM,但在实际重新启动之前它会换出 5 倍。所以你 可以 超过 512mb(只要你愿意为交换到磁盘支付性能损失,这可能很严重)。
除此之外,Heroku 按秒计费,并允许您根据需要上下调整测功机编队。这在您自己的应用程序中通过点击 Heroku API 很容易实现 – 我看到您已经用 NodeJS 标记了它,所以您可能想查看:
- Heroku's node client
- 非常准系统但仍能正常工作的 toots/node-heroku 模块
这两个模块都允许您按比例放大和缩小测功机的编队 — 通过简单的启发式算法(例如,总是有一个备用的 1X 测功机 运行ning),您可以在进行时增加容量处理请求,并在 api 请求未 运行ning 时摆脱备用容量。鉴于您按秒计费,这最终可能会非常便宜; 1X dynos 可以在 小时 到 运行 之间计算出 5¢。如果您最终 运行 每天使用几个小时的额外测功机,这对您来说是非常非常小的成本。
最后:还有第 3 方服务,例如 Adept and Hirefire(来自 Google 的两个随机示例,我相信还有更多)可以让您在某种程度上实现自动化,但是我对他们没有任何经验。
我是 Heroku 的 Node.js 平台所有者。
您可能进行了一些过早的优化。 Node.js,在我们最小的 1X 大小(512MB RAM)上,每分钟可以处理数百个并发连接和数千个请求。
如果您的 iOS 应用始终将其最大化,可能是时候考虑获利了!
我有一个网络应用程序可以接受来自 ios 应用程序的 api 请求。我的网络应用程序托管在 Heroku 上,使用他们的免费测功机,每个请求能够处理 512 MB 的数据。因为节点是一个单线程应用程序,所以一旦我们开始从 ios 端到 Web 服务器获得更高级别的流量,这将是一个问题。我也不是世界上最富有的人,所以我想知道创建另一个免费的 heroku 应用程序并使用循环法来平衡从 ios 应用程序收到的负载是否明智?
我只需要指出正确的方向。垂直扩展在财务上并不是一个真正的选择。
你当然可以,我的意思是,以编程方式 - 但那会绕过 Heroku's TOS:
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.
有一些线程在讨论这个问题,并给出了一些有趣的答案:
Clustering Node JS in Heavy Traffic Production Environment
How to decide when to use Node.js?
此外,他们 link 观看了该视频,介绍了 Node.js,其中讨论了一些基准测试:
正如 Daniel 所提到的,它违反了 Heroku 规则。话虽如此,可能还有其他服务可以让您这样做。 解决此问题的一种方法是将集群模块与 ZeroMQ (you need to have ZeroMQ installed before using the module - see 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
})
}
这只是为您指明正确的方向。如果您考虑一下,您可以创建一个带有参数的脚本,该参数将告诉它它是主进程还是工作进程。然后在主服务器上 运行 它是原样,在其他服务器上 运行 它使用 worker 标志,这将强制它连接到主要经销商。
现在您的主应用需要将请求发送到路由器,稍后将转发到工作进程:
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 的限制违反了他们的服务条款,这可能不是一个好主意。
不过,也有一些好消息。对于初学者(来自 Heroku's docs):
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.
据我了解,尽管您的测功机有 512mb 的 实际 RAM,但在实际重新启动之前它会换出 5 倍。所以你 可以 超过 512mb(只要你愿意为交换到磁盘支付性能损失,这可能很严重)。
除此之外,Heroku 按秒计费,并允许您根据需要上下调整测功机编队。这在您自己的应用程序中通过点击 Heroku API 很容易实现 – 我看到您已经用 NodeJS 标记了它,所以您可能想查看:
- Heroku's node client
- 非常准系统但仍能正常工作的 toots/node-heroku 模块
这两个模块都允许您按比例放大和缩小测功机的编队 — 通过简单的启发式算法(例如,总是有一个备用的 1X 测功机 运行ning),您可以在进行时增加容量处理请求,并在 api 请求未 运行ning 时摆脱备用容量。鉴于您按秒计费,这最终可能会非常便宜; 1X dynos 可以在 小时 到 运行 之间计算出 5¢。如果您最终 运行 每天使用几个小时的额外测功机,这对您来说是非常非常小的成本。
最后:还有第 3 方服务,例如 Adept and Hirefire(来自 Google 的两个随机示例,我相信还有更多)可以让您在某种程度上实现自动化,但是我对他们没有任何经验。
我是 Heroku 的 Node.js 平台所有者。
您可能进行了一些过早的优化。 Node.js,在我们最小的 1X 大小(512MB RAM)上,每分钟可以处理数百个并发连接和数千个请求。
如果您的 iOS 应用始终将其最大化,可能是时候考虑获利了!