如何在多服务器环境中使用服务器端观察者?

我最近添加了另一台服务器到我的应用程序,并放置在他们面前的Nginx负载平衡器。 所以负载均衡器和两个运行相同应用的服务器。 这对我来说都是非常新的,而且我遇到了在单一服务器环境中不会遇到的问题。 其中之一就是应用程序的服务器端观察者在两个服务器上运行,这是不可取的。 例如,我将有以下观察者。

var initializing = true; Jobs.find({ $or: [{ processed: { $ne: true } }, { restart: true }] }).observeChanges({ added: function(id, doc) { if (!initializing) { // do stuff } } }); initializing = false; 

然后在两台服务器上运行。 我只希望它运行在一个 – 我不在乎哪一个,但我猜是用户目前正在使用的是合理的。 我有什么select? 我不认为这是一个不寻常的情况,但我无法在网上find任何东西。 我目前的解决方法是从服务器中删除观察者,并有一个第三服务器,所有的观察。 但是,如果我的应用程序起飞,这不会扩展,这显然我希望它。 谢谢你的帮助。

我将介绍两个可能的解决方案:指定的主控和动态主控。

指定的主人

在这个策略中,我们将选择一个服务器作为工作任务的“主”。 有很多种方法可以做到这一点,但正如上面提到的@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集合(而不是观察其更改)是否符合您的用例。

正如你所提到的,你正在使用nginx。 Nginx可以对上游模块做服务器关联。 这将确保每个客户端将会碰到同一台服务器。 服务器亲和力有很多缺点,但是流星可以自己使用服务器亲和力。

 upstream backend { server backend1.example.com; server backend2.example.com; sticky cookie srv_id expires=1h domain=.example.com path=/; } 

还有其他的方法与nginx。 以上是cookie方法,但可以使用routelearn

http://nginx.org/en/docs/http/ngx_http_upstream_module.html