【问题标题】:Sending many requests from Node.js to an API causes error从 Node.js 向 API 发送许多请求会导致错误
【发布时间】:2017-12-08 02:08:30
【问题描述】:

我的数据库中有超过 2000 个用户,当我尝试向所有用户广播消息时,它几乎没有发送大约 200 个请求,然后我的服务器停止了,我收到如下错误:

{ Error: connect ETIMEDOUT 31.13.88.4:443
at Object.exports._errnoException (util.js:1026:11)
at exports._exceptionWithHostPort (util.js:1049:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
code: 'ETIMEDOUT',
errno: 'ETIMEDOUT',
syscall: 'connect,
address: '31.13.88.4',
port: 443 }

有时我收到另一个错误提示:

Error!: Error: socket hang up 

这是我的要求:

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: '#####' },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      if (messageId) {
        console.log("Successfully sent message with id %s to recipient %s", 
          messageId, recipientId);
      } else {
      console.log("Successfully called Send API for recipient %s", 
        recipientId);
      }
    } else {
      console.error("Failed calling Send API");
      console.log(error)
    }
  });  
}

我试过了

setTimeout 让 API 调用等待一段时间:

 setTimeout(function(){callSendAPI(data)},200);

如果遇到类似错误,谁能帮忙?

已编辑

我正在使用 Messenger 平台,它支持对发送 API 的高调用率,并且不限于 200 次调用。

【问题讨论】:

  • @mplungjan 我做了,但我没有得到与 http.request 相关的答案
  • q=ETIMEDOUT+node.js+POST+facebook
  • 您是否正在向 graph.facebook.com 发出 2000 个并发请求并想知道为什么会失败? :)
  • @JeremyThille 对不起!发出 2000 个请求有什么问题?我没有直接使用graph.API ..我通过没有限制的Graphs使用Messenger API。
  • 哦,那不一样了,如果是messenger API就对了。

标签: javascript node.js facebook api node-request


【解决方案1】:

听起来您正在达到速率限制。

来自Facebook documentation

您的应用总共可以为每位用户每小时拨打 200 次电话。

您可以检查dashboard,看看在这些情况下您是否达到了速率限制。

【讨论】:

【解决方案2】:

您可能会达到 Facebook API 的限制。要限制请求,您应该在前一个请求的某个时间间隔后发送每个请求。您没有包括迭代所有用户的位置,但我怀疑您可能会在循环中执行此操作,如果您使用 setTimeout 以 200 毫秒的延迟延迟每个请求,那么您将同时完成所有请求,例如你以前做过 - 仅仅 200 毫秒之后。

你可以做的是:

  1. 您可以使用 setTimeout 并为每个请求添加可变延迟(不推荐)
  2. 您可以使用 Async 模块的 seriesparallelLimit(使用回调)
  3. 您可以使用 Bluebird 的 Promise.mapSeriesPromise.mapconcurrency 限制(使用承诺)

不建议使用 1,因为它仍然是一劳永逸的(除非您为此添加更多复杂性),并且您仍然冒着并发过多和超出限制的风险,因为您只能控制请求何时开始,不是有多少未完成的请求。

2 和 3 大体相同,但不同之处在于使用回调或承诺。在您的示例中,您正在使用回调,但您的 callSendAPI 不采用自己的回调,如果您希望选项 2 起作用,它应该这样做 - 或者,如果您希望选项 3 起作用,它应该返回一个承诺。

有关更多信息,请参阅文档:

当然还有更多方法可以做到这一点,但这些是最简单的。

理想情况下,如果您想充分利用每小时 200 个请求的限制,那么您应该自己对请求进行排队,并按照与该限制相对应的特定间隔发出请求。有时如果你在一小时内没有做很多请求,那么你就不需要延迟,有时你会。您在这里真正应该做的是将所有请求集中排队,并以与已用完部分相对应的间隔清空队列,直到您应该跟踪自己的限制 - 但这可能很棘手。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 2018-01-02
  • 2015-03-20
  • 1970-01-01
  • 2018-09-06
  • 2019-08-10
  • 2020-02-04
相关资源
最近更新 更多