两台服务器之间的DDP不会重新连接

时间:2013-10-25 15:51:44

标签: meteor

我有两个通过DDP连接在不同服务器上的流星应用程序,服务器A将数据发送到服务器B.这就是它们的工作方式。

服务器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);
  }
});

每次我在服务器A上调用Items.insert(something)时,在服务器BI上都会在控制台上记录我在服务器A上保存的对象。但是如果服务器B丢失了Internet连接,则在服务器A上插入的数据不会当服务器B重新连接到Internet时,它将再次出现在服务器B上。

服务器B通过路由器连接到Internet。此问题仅在我断开连接并重新连接路由器时发生,而不是在我断开连接并从路由器重新连接服务器时。两台服务器都在不同的网络上,并通过Internet连接。

我在服务器B上创建了一个调用remote.status()但在连接或断开互联网时始终获得{ status: 'connected', connected: true, retryCount: 0 }的计时器。

更新:重现的步骤

我在github上创建了一个带有测试代码https://github.com/camilosw/ddp-servers-test的项目。服务器A安装在http://ddpserverstest-9592.onmodulus.net/

我的电脑通过无线电缆调制解调器连接到互联网。

  1. 在server-b文件夹上运行mrt
  2. 转到http://ddpserverstest-9592.onmodulus.net/并单击“插入”链接(您可以单击“删除”以删除所有以前的插入内容)。您必须在本地控制台上看到添加了项目的消息。
  3. 关闭计算机上的无线功能,然后再次单击插入链接。 (您需要点击另一台可以访问Internet的计算机,我使用智能手机点击链接)
  4. 打开电脑上的无线设备。您必须在本地控制台上看到第二项消息。
  5. 现在,关闭有线调制解调器并再次单击插入链接。
  6. 打开电缆调制解调器。这次,新项目不会出现在控制台上。
  7. 我也使用Android智能手机使用选项通过无线方式将Internet共享到我的电脑。首先,我关闭了计算机上的无线网络并正常工作。然后我关闭了智能手机上的互联网连接,我遇到了同样的问题。

    更新2

    我的办公室里有两个无线路由器。我发现如果我在路由器之间移动会发生同样的问题。

3 个答案:

答案 0 :(得分:3)

来自Meteor团队的Emily Stark证实,这是由于当前实施中缺少一个功能(我写这个答案时的版本0.7.0.1)。他们的回答是https://github.com/meteor/meteor/issues/1543。以下是他们的回答以及她建议的解决方法:

服务器到服务器的连接没有重新连接,因为Meteor当前没有对服务器到服务器的DDP连接进行任何检测。就像在任何其他TCP连接中一样,一旦切换到不同的路由器,连接上就不能发送或接收任何数据,但客户端将不会注意到,除非它尝试发送一些数据并超时。这与在SockJS上运行的浏览器到服务器DDP连接不同。 SockJS有自己的心跳,我们可以用它来检测死连接。

要查看此操作,以下是我在示例中添加到server-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");
};

在此处添加了此代码后,server-b将在经过足够长的时间后重新连接,而不会发送来自服务器的ACK-a用于提供心跳方法调用的TCP段。在我的机器上,这只是几分钟,我得到一个ETIMEDOUT,然后重新连接。

我已经开设了一个单独的任务,让我们考虑在下一个bug周期间在服务器到服务器DDP连接上实现心跳。与此同时,您可以始终在应用程序中实现心跳,以确保在客户端无法再与服务器通信时发生DDP重新连接。

答案 1 :(得分:1)

我认为您没有正确地将DDP连接对象传递给Collection,请尝试:

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

调试首先从浏览器控制台尝试所有这些连接游戏可能很有用,因为Meteor在客户端上提供了相同的连接/集合API(控制流除外)。只需打开任何Meteor应用程序,然后从控制台尝试这一行。

答案 2 :(得分:0)

我根据camilosw的代码修改了两个ddp服务器之间的通信示例。

服务器A作为云数据中心。服务器B作为数据源,如果某些数据发生了变化,应该发送到服务器A.

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

中找到代码
相关问题