2

我有两个通过 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);
  }
});

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

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

我在服务器 B 上创建了一个计时器,该计时器在连接或断开 Internet 时remote.status()总是会调用。{ status: 'connected', connected: true, retryCount: 0 }

更新:重现步骤

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

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

  1. 在 server-b 文件夹上运行 mrt
  2. 转到http://ddpserverstest-9592.onmodulus.net/并单击链接插入(您可以单击删除以删除所有以前的插入)。您必须在本地控制台上看到一条消息,其中包含添加的项目。
  3. 关闭计算机上的无线并再次单击插入链接。(你需要点击另一台可以上网的电脑,我用智能手机点击链接)
  4. 打开电脑上的无线。您必须在本地控制台上看到一条带有第二项的消息。
  5. 现在,关闭电缆调制解调器并再次单击插入链接。
  6. 打开电缆调制解调器。这一次,新项目没有出现在控制台上。

我还使用 android 智能手机使用通过无线共享 Internet 到我的计算机的选项来做到这一点。首先,我关闭并打开计算机上的无线网络并正常工作。然后我关闭并打开智能手机上的互联网连接,我遇到了同样的问题。

更新 2

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

4

3 回答 3

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");
};

在那里添加此代码后,服务器-b 将在经过足够长的时间后重新连接,而服务器-a 没有对传递心跳方法调用的 TCP 段发出 ACK。在我的机器上,这只是几分钟,然后我得到一个 ETIMEDOUT,然后重新连接。

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

于 2014-01-13T13:07:10.747 回答
2

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

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

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

于 2013-10-26T20:50:46.340 回答
0

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

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

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

于 2015-04-24T16:59:44.243 回答