使用 node.js 客户端的网络超时大约 5 秒

Network timeout using node.js client at about 5 seconds

注意,这个问题以前是非常不同的。这才是真正的问题。这是...

当使用 node.js client 调用 executeStoredProcedure() 时,我得到一个 408 代码,RequestTimeout,并且我没有从存储过程的 "body" 返回任何数据。这似乎发生在大约 5 秒时,但是当我从 sproc 本身内部对事物进行时间限制时,任何超过 700 毫秒的值都会导致我获得网络超时(尽管我直到大约 5 秒后才看到它)。

请注意,我可以使用更长的 运行 存储过程进行读取操作。这似乎只有在我有很多 createDocument() 操作时才会发生,所以我认为它不在客户端。我认为服务器端发生了一些事情。

我最初的想法仍然有可能是正确的,并且我没有从 createDocument() 调用中得到错误返回,这导致我的存储过程保持 运行 超过其超时,这就是导致 408 的原因。

这是我创建文件sproc的限时版本

generateData = function(memo) {
  var collection, collectionLink, nowTime, row, startTime, timeout;
  if ((memo != null ? memo.remaining : void 0) == null) {
    throw new Error('generateData must be called with an object containing a `remaining` field.');
  }
  if (memo.totalCount == null) {
    memo.totalCount = 0;
  }
  memo.countForThisRun = 0;
  timeout = memo.timeout || 600; // Works at 600. Fails at 800.
  startTime = new Date();
  memo.stillTime = true;
  collection = getContext().getCollection();
  collectionLink = collection.getSelfLink();
  memo.stillQueueing = true;
  while (memo.remaining > 0 && memo.stillQueueing && memo.stillTime) {
    row = {
      a: 1,
      b: 2
    };
    getContext().getResponse().setBody(memo);
    memo.stillQueueing = collection.createDocument(collectionLink, row);
    if (memo.stillQueueing) {
      memo.remaining--;
      memo.countForThisRun++;
      memo.totalCount++;
    }
    nowTime = new Date();
    memo.nowTime = nowTime;
    memo.startTime = startTime;
    memo.stillTime = (nowTime - startTime) < timeout;
    if (memo.stillTime) {
      memo.continuation = null;
    } else {
      memo.continuation = 'Value does not matter';
    }
  }
  getContext().getResponse().setBody(memo);
  return memo;
};

上面的存储过程在 while 循环中创建队列文档,直到 API returns false.

请记住 createDocument() 是一种异步方法。布尔值 returned 表示是否该立即结束执行。 return 值不足以 "smart" 来估计和说明异步调用将花费多少时间;所以它不能用于在 while() 循环中对一堆调用进行排队。

因此,当布尔值 returns false 时,上面的存储过程不会正常终止,因为它有一堆 createDocument() 调用仍然是 运行 .最终结果是超时(最终导致重复尝试被列入黑名单)。

简而言之,避免这种模式:

while (stillQueueing) {
  stillQueueing = collection.createDocument(collectionLink, row);
}

相反,您应该使用回调来控制流程。这是重构后的代码:

function(memo) {
  var collection = getContext().getCollection();
  var collectionLink = collection.getSelfLink();
  var row = {
    a: 1,
    b: 2
  };

  if ((memo != null ? memo.remaining : void 0) == null) {
    throw new Error('generateData must be called with an object containing a `remaining` field.');
  }
  if (memo.totalCount == null) {
    memo.totalCount = 0;
  }
  memo.countForThisRun = 0;

  createMemo();

  function createMemo() {
    var isAccepted = collection.createDocument(collectionLink, row, function(err, createdDoc) {
      if (err) throw err;

      memo.remaining--;
      memo.countForThisRun++;
      memo.totalCount++;

      if (memo.remaining > 0) {
        createMemo();
      } else {
        getContext().getResponse().setBody(memo);
      }
    });

    if (!isAccepted) {
      getContext().getResponse().setBody(memo);
    }
  }
};