2013-10-25 76 views
2

我有兩個流星應用通過DDP連接到不同的服務器,服務器A發送數據到服務器B.這是他們的工作方式。兩臺服務器之間的DDP不能重新連接

服務器A

Items = new Meteor.Collection('items'); 
Items.insert({name: 'item 1'}); 
if (Meteor.isServer) { 
    Meteor.publish('items', function() { 
    return Items.find(); 
    }); 
} 

服務器B

var remote = DDP.connect('http://server-a/'); 
Items = new Meteor.Collection('items', remote); 

remote.subscribe('items'); 
Items.find().observe({ 
    added: function(item) { 
    console.log(item); 
    } 
}); 

每次我打電話Items.insert(something)在服務器A上,在服務器BI得到了與該對象的控制檯上的日誌我救在服務器A但如果服務器B丟失了Internet連接,則服務器B上插入的數據在重新連接到Internet時不會再出現在服務器B上。

服務器B通過路由器連接到Internet。只有當我斷開並重新連接路由器時,纔會發生此問題,而不是斷開連接並從路由器重新連接服務器。兩臺服務器都在不同的網絡上並通過互聯網連接。

我在服務器B上創建了一個定時器,它調用remote.status(),但在連接或斷開Internet時始終會獲得{ status: 'connected', connected: true, retryCount: 0 }

更新:重現步驟

我與測試代碼https://github.com/camilosw/ddp-servers-test github上創建的項目。服務器A安裝在http://ddpserverstest-9592.onmodulus.net/

我的電腦通過無線電纜調制解調器連接到Internet。

  1. 地鐵運行在服務器上-B文件夾
  2. 轉到http://ddpserverstest-9592.onmodulus.net/並單擊鏈接插入(您可以點擊刪除刪除所有先前的插入)。您必須在本地控制檯上看到添加了項目的消息。
  3. 關閉計算機上的無線連接,然後再次單擊插入鏈接。 (您需要點擊另一臺可以上網的電腦,我用智能手機點擊鏈接)
  4. 打開電腦上的無線網絡。您必須在第二個項目的本地控制檯上看到一條消息。
  5. 現在,關閉電纜調制解調器並再次單擊插入鏈接。
  6. 打開電纜調制解調器。這一次,新項目不會出現在控制檯上。

我也做了一個android智能手機使用選項,通過無線共享Internet到我的電腦。首先,我關掉電腦上的無線設備並開始正常工作。然後關掉智能手機上的互聯網連接,我也遇到了同樣的問題。

更新2

我有我的辦公室兩個無線路由器。我發現如果我在路由器之間移動,也會發生同樣的問題。

+0

的代碼,這可能涉及到https://github.com/meteor/meteor/issues/1724 – imslavko

+0

這個問題是我在github上打開的問題的一個副本https://github.com/meteor/meteor/issues/1543 – Camilo

+0

哦,我很抱歉,隨機發現它並認爲它會有關係。沒有看實際的名字。是的,抱歉我的答案根本沒有任何幫助,事實上這是應該用某種心跳來解決的問題。 – imslavko

回答

3

來自Meteor團隊的Emily Stark證實,這是由於當前實現中缺少一個功能(當我寫這個答案時,版本爲0.7.0.1)。他們的答案在這裏https://github.com/meteor/meteor/issues/1543。以下是他們的答案和她建議的解決方法:

服務器到服務器的連接沒有重新連接,因爲Meteor目前沒有在服務器到服務器DDP連接上執行任何心跳檢測。就像在任何其他TCP連接中一樣,一旦切換到另一個路由器,就不會在連接上發送或接收任何數據,但客戶端不會通知它,除非它嘗試發送一些數據並超時。這與通過SockJS運行的瀏覽器到服務器DDP連接不同。 SockJS有自己的心跳,我們可以用它來檢測死連接。

要看到這個動作,這裏是一些代碼,我加入到服務器-B在你的榜樣:

var heartbeatOutstanding = false; 
Meteor.setInterval(function() { 
    if (! heartbeatOutstanding) { 
    console.log("Sending heartbeat"); 
    remote.call("heartbeat", function() { 
     console.log("Heartbeat returned"); 
     heartbeatOutstanding = false; 
    }); 
    heartbeatOutstanding = true; 
    } 
}, 3000); 

remote.onReconnect = function() { 
    console.log("RECONNECTING REMOTE"); 
}; 

有了這個代碼在裏面添加,足夠長的時間去後服務器-B將重新連接通過沒有來自服務器a的ACK來執行心跳方法調用的TCP段。在我的機器上,這只是幾分鐘,然後我得到一個ETIMEDOUT,然後重新連接。

我已經打開了一個單獨的任務,讓我們考慮在下一個bug週期間在服務器到服務器DDP連接上實現心跳。同時,您始終可以在您的應用程序中實施心跳檢測,以確保如果客戶端無法再與服務器通話,就會發生DDP重新連接。

1

我想你是不是正確傳遞DDP連接對象的集合,請嘗試:

var remote = DDP.connect('http://server-a/'); 
Items = new Meteor.Collection('items', { connection: remote }); 

這可能是有用的調試首先嚐試從瀏覽器控制檯所有這些連接遊戲,因爲流星提供相同客戶端連接/集合的API(控制流除外)。只需打開任何Meteor應用程序並從控制檯嘗試這些行。

+0

顯然這兩種方式的工作原理是一樣的。我試過你的代碼,但它不能解決問題。 – Camilo

+0

然後我不能建議任何東西,但張貼複製。服務器到服務器ddp是我們每天在內部使用的Meteor DG的一部分。值得注意的是,Galaxy幾乎在任何地方都依賴於服務器到服務器的ddp,所以我認爲它沒有辦法被遺忘或過時。 – imslavko

+0

感謝您的支持imslavko。我更詳細地更新了我的問題。 – Camilo

0

我修改了基於camilosw代碼的兩個ddp服務器之間的通信樣本。

服務器A作爲雲端數據中心。服務器B作爲數據源,如果一些數據改變了,應該發送到服務器A.

您可以找到https://github.com/iascchen/ddp-servers-test

相關問題