2014-06-16 39 views
3

我的NodeJS客户端能够根据需要连接到MongoDB主服务器并与之交互。来自NodeJS的MongoDB复制连接

我用下面的代码来构建一个服务器对象

var dbServer = new Server(
    host, // primary server IP address 
    port, 
    { 
     auto_reconnect: true, 
     poolSize: poolSize 
    }); 

和下面的代码来创建数据库对象:

var db = new Db(
    'MyDB', 
    dbServer, 
    { w: 1 } 
); 

我的印象是,当主下山,客户会自动发现它现在需要与其中一位副局长谈话,他们将被选为主要委员。

但是,当我手动杀死主服务器时,其中一台辅助服务器确实成为主服务器(从它的mongo shell可以观察到,并且它现在响应mongo shell命令),但客户端没有自动与它交谈。如何配置NodeJS服务器自动切换到辅助?

难道,我需要指定所有3个服务器地址?但这似乎并不是一个好的解决方案,因为一旦主要网络恢复正常,它的IP地址将与原来的IP地址不同。

我觉得我失去了一些东西很基本的,请赐教:)

谢谢你, 加里

回答

4

嗯,你的理解是部分存在,但也存在一些问题。在连接中分配多个单个服务器的一般前提是,如果在连接时该服务器地址不可用,则将选择“种子列表”中的其他内容来建立连接。这样可以消除单点故障,例如此时“主”不可用。

如果这是一个“副本集”,那么驱动程序会在连接后发现成员,然后在该成员当选时自动切换到新的“主”。所以这确实要求你的“副本集”实际上能够选择一个新的“主”来切换连接。此外,这不是“即时”的,所以在新的“主要”被提升并且能够接受操作之前可能会有延迟。

你的“auto_reconnect”设置也没有做你认为它正在做的事情。所有这些管理是,如果发生连接“错误”,驱动程序将“自动”重试连接而不会引发异常。你可能真的想要做的就是自己处理这个问题,因为你可能会无限重试一个无法建立的连接。所以好的代码会考虑到这一点,并通过一些合理的处理和日志记录来管理“重新连接”本身。

通常通过使用主机名来解决IP地址的最终问题,这些主机名可以解析为这些“主机名”从不改变的IP地址,而不管它们解决什么问题。这对驱动程序来说同样适用于“副本集”本身。事实上,如果服务器成员正在通过更改的IP地址寻找另一个成员,那么他们不知道要寻找什么。

因此,驱动程序将“故障转移”或以其他方式选择新的可用“主”,但只能在服务器可以相互通信的相同容差范围内。你应该种子你连接,因为你不能保证当你连接时哪个节点是“主”。最后你应该使用主机名而不是IP地址,如果后者可能会改变。

驱动程序将“自我发现”,但它只是使用可用于副本集的配置才能这样做。如果该配置对副本集无效,那么它对驱动程序也是无效的。

实施例:

MongoClient.connect("mongodb://member1,member2,member3/database", function(err,db) { 

}) 

或者其他与Server对象的数组代替。

+0

尼尔,感谢您的详细解释。我根据您的建议进行了更改,现在客户端在主服务器出现故障时切换到次服务器。如果您不介意,我有几个问题需要注意:1.当我杀死2台数据库服务器时,只留下一台服务器,客户端无法再连接,您能否介绍一下为什么?另外,我在AWS EC2上托管客户端服务器和mongo服务器,所以我想我可以分配/分配给我一个内部IP地址池,当我重新启动发生故障的服务器时,可以为其分配IP地址。 –

+0

和关于auto_reconnect,因为客户端和数据库服务器都在AWS内部,我真的需要担心客户端无法连接到数据库服务器吗?我想,这只会在所有副本成员死亡或AWS有内部网络问题时才会发生。再次感谢您的反馈。 –

+1

@GaryKipnis这两个有点过于宽泛,但杀害两个实例的一般情况导致我相信其余成员不再形成多数,因此没有“主要”左派。其次,始终认为连接可以消失。即使AWS在同一地区,您也无法确定实例之间是否存在网络分区,或者即使它们实际上没有确定的计划保证位于同一数据中心。您可能有更适合复制的[dba.stackexchange.com](http://dba.stackexchange.com)问题。 –