2014-06-16 71 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)問題。 –