2014-05-10 22 views
1

的貓鼬連接到副本集的一個常見的連接字符串是一樣的東西如下麻煩貓鼬重新連接到節點和發送請求到次級

var connection = mongoose.createConnection("mongodb://db_1:27017/client_test,mongodb://db_2:27017/client_test", { 
    replSet : { rs_name : "rs0", poolSize : 5, socketOptions : { keepAlive : 1 } } 
}, function(err) { 
    if (err) { throw err; } 
}); 

與問題是如果兩臺主機的人下來,那麼它將無法連接。如果你只指定一個主機,那麼沒有請求最終被髮送到輔助節點。

這是我對這一說法的證據。如果指定一個主機,並設置你的副本設置,以便有一個小學和一個仲裁,然後執行一個查詢如

myApi.find({}).slaveOk().read("s").exec(function(err, docs) { 
    console.log(docs) 
}) 

它會返回結果。那麼,因爲我指定「s」(輔助),這個查詢應該會拋出一個錯誤,因爲沒有運行的輔助數據庫。另外,如果你把二級在線,然後做db.currentOp(true),你永遠不會看到任何實際的查詢發送它的方式。

當您更改連接字符串以指定每個主機時,您將看到連接轉到輔助。目前的困境是,因爲必須在連接字符串中指定其他主機,所以如果次要服務器處於脫機狀態,它將無法連接,並且現在我們失去了故障轉移功能(或將整個點指向副本集)

我不能確定這是否是我的配置錯誤,Mongoose中的錯誤,或者是我理解副本集函數方式的概念缺陷。從一些文檔中,他們似乎認爲從二手文字閱讀基本上是一個壞主意,但這樣做的原因通常是陳舊數據的問題。我的問題與過時的日期沒有任何關係,我無法找到一種設置系統的方式,以便我可以在不損失故障切換容量的情況下查詢輔助數據。

回答

0

好吧,我相信我解決了我所有的問題。這是我學到的東西。

  1. 在連接字符串中指定所有可能的副本節點,否則Mongoose將永遠不會在那裏發送請求。 Mongoose有一個特定的格式,與node-mongodb-native驅動程序不同。下面的例子。

  2. 爲了防止其中一個節點在啓動時停機,您需要在'replset'選項中指定connectTimeoutMS,那麼它將只等待初始連接上每個節點的響應。如果節點稍後聯機,它仍然可用。

  3. 在MongoDB的副本設置的主機名條目需要從你的應用程序和匹配連接字符串中的主機名條目所有主機名必須是可訪問的各方(蒙戈以蒙戈和應用,以蒙戈)。在我的情況下,我已經將mongo的主機名別名爲mongo,分別爲mongo1:27017,mongo2:27017mongo3:27017。我的應用程序服務器使用連接字符串與IP。 Mongoose試圖使用主機名(我的應用服務器無法訪問)而不是我在連接字符串中指定的IP地址重新啓動連接。這導致它不會重新連接到它失去聯繫的節點。我有可能使用了應用程序可以達到的主機名,但它仍然可以工作,但我認爲最好的做法是使連接字符串和副本設置完全相同,以便刪除可能發生錯誤的位置。

  4. 在你rs.initiate()可能需要更新的主機名是所有箱子(其他mongodbs和應用服務器可以達到)值MongoDB的節點。默認情況下,它最終可能會有一個主機名,如localhost,這意味着每臺機器上都有不同的東西。這可以從mongo shell那樣的盒子中得到。

實施例:它成功地故障轉移節點,包括如果查詢註定用於二次但目前還沒有次級引發錯誤之間

// from mongo shell 
conf = rs.conf() 
conf.members[0].host = "mongo1:27017" 
rs.reconfig(conf) 

最終功能連接字符串。

var connection = mongoose.createConnection("mongodb://mongo1:27017/client_test,mongo2:27017/client_test,mongo3:27017/client_test", { 
    replset : { rs_name : "rs0", poolSize : 5, socketOptions : { keepAlive : 1, connectTimeoutMS : 1000 } }, 
}, function(err) { 
    if (err) { throw err; } 
}); 

工作副本設置

{ 
     "_id" : "rs0", 
     "version" : 4, 
     "members" : [ 
       { 
         "_id" : 0, 
         "host" : "mongo1:27017" 
       }, 
       { 
         "_id" : 1, 
         "host" : "mongo2:27017" 
       }, 
       { 
         "_id" : 2, 
         "host" : "mongo3:27017", 
         "arbiterOnly" : true 
       } 
     ] 
} 
0

1.連接字符串只是定義了種子服務器,mongodb驅動程序試圖連接到這些服務器並通過調用rs.status()獲取有關replicaSet中其他服務器的信息。你可以有5個節點的replicaSet,但是隻能在連接字符串中指定一個,但如果連接字符串的服務器可用,驅動程序將能夠找到其他四個節點。

2.我的建議是使用secondaryPreferred而不是隻有secondary,以便在沒有輔助可用的情況下,將對主要進行請求。

+0

這是有道理的,除非我指定一個種子服務器,請求不會最終轉到輔助(不管我是否使用'sp'或's')。 「次要」的用法是爲了證明這一點,因爲沒有第二次就會失敗。 – Nucleon

0

我不得不與你類似的一些問題,在處理副本,在我來說,我有1個主節點爲10的優先級,0 1個次要地位(對分析)和仲裁者。 我寫將重新連接主實例失敗後,我經歷了很多嘗試修復,這是我學到的最重要的事情:

當我的主服務器停機或unreacheable,必須有資格另一名成員成爲主要成員(我的集體中至少有2名成員的優先級大於等於1)。 如果我只有仲裁者,隱藏或優先級爲0的成員,則 即使在我重新連接主服務器後,查詢也會卡住,但我的客戶端無法完成寫查詢,因此我的客戶端爲 。閱讀查詢仍然有效,但 寫不會。

這就是我面臨的貓鼬,即使有keepalive,autoreconnect和所有套接字和連接超時MS設置。

希望這會有所幫助。

+0

deb2fast - 你是如何解決這個問題的? – user3658423

+0

@ user3658423我在上面發佈了我的答案,你是否面臨類似的問題?你可以發佈一個鏈接到你的問題,我會檢查出來。 – deb2fast