我最近在我的应用程序中添加了另一台服务器,并在它们前面放置了一个Nginx负载均衡器。所以负载均衡器和运行相同应用程序的两台服务器。这对我来说都是全新的,我遇到了在单一服务器环境中不会遇到的问题。其中之一是应用程序上的服务器端观察者在BOTH服务器上运行,这是不可取的。例如,我将有以下观察者。
var initializing = true;
Jobs.find({
$or: [{
processed: {
$ne: true
}
}, {
restart: true
}]
}).observeChanges({
added: function(id, doc) {
if (!initializing) {
// do stuff
}
}
});
initializing = false;
然后在两台服务器上运行。我只想让它在一个上运行 - 我不关心哪一个,但我想用户当前使用的那个是有意义的。我有哪些选择?我不认为这是一个不常见的情况,但我无法在网上找到任何东西。我目前的解决方法是从服务器上删除观察者,并拥有一个执行所有观察的第三个服务器。但是,如果我的应用程序起飞,这将无法扩展,显然我希望它能做到。谢谢你的帮助。
答案 0 :(得分:2)
我将针对此问题提出两种可能的解决方案:指定主服务器和动态主服务器。
在这个策略中,我们将选择一个服务器作为" master"为了工作任务。有多种方法可以做到这一点,但正如上面提到的@sbking,使用环境变量可能是最简单的方法。在其中一台服务器上,设置一个类似MASTER_SERVER=1
的变量。在所有服务器上,您可以检查是否存在所述变量,并仅在设置任务时运行该任务。例如:
服务器启动脚本
export PORT=3000
export ROOT_URL=https://app.example.com
export MASTER_SERVER=1
forever start /path/to/your/bundle/main.js
服务器B启动脚本
export PORT=3000
export ROOT_URL=https://app.example.com
forever start /path/to/your/bundle/main.js
服务器/ main.js 强>
if (process.env.MASTER_SERVER) {
Jobs.find(...).observeChanges(...);
}
因为只有A以MASTER_SERVER
设置启动,所以它将是执行任务的唯一服务器。虽然这种策略很容易实现,但它有一个严重的缺陷 - 它不具备容错能力。如果A失败,任务将无法继续运行。
不是预先指定主设备,而是每个服务器尝试定期成为主设备的替代方法。如果您可以将任务转换为看起来像cron作业的内容,则此策略很有效。然后,您只需使用synced-cron,这将确保只有一个服务器可以在该间隔期间执行任务。在此示例中,每个服务器将尝试每分钟运行一次任务:
服务器/ main.js 强>
SyncedCron.add({
name: 'Process all the things!',
schedule: function(parser) {
return parser.text('every 1 mins');
},
job: function() {
// do job processing here
return true;
}
});
SyncedCron.start();
这是一个更强大的解决方案,但您需要确定定期检查Jobs
集合(而不是观察其更改)是否适合您的用例。
答案 1 :(得分:0)
正如您所提到的,您使用的是nginx。 Nginx可以对上游模块执行服务器关联。这将确保每个客户端将命中相同的服务器。服务器亲和性有许多缺点,但meteor自行使用服务器亲和力。
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky cookie srv_id expires=1h domain=.example.com path=/;
}
nginx还有其他方法。以上是cookie
方法,但可以使用route
或learn