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

时间:2015-01-03 23:00:55

标签: nginx meteor

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

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

然后在两台服务器上运行。我只想让它在一个上运行 - 我不关心哪一个,但我想用户当前使用的那个是有意义的。我有哪些选择?我不认为这是一个不常见的情况,但我无法在网上找到任何东西。我目前的解决方法是从服务器上删除观察者,并拥有一个执行所有观察的第三个服务器。但是,如果我的应用程序起飞,这将无法扩展,显然我希望它能做到。谢谢你的帮助。

2 个答案:

答案 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方法,但可以使用routelearn

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