从 Node.js 向 API 发送许多请求会导致错误
Sending many requests from Node.js to an API causes error
我的数据库中有 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);
如果 he/she 遇到类似的错误,有人可以提供帮助吗?
已编辑
我使用的 Messenger 平台支持发送 API 的高调用率,并且不限于 200 次调用。
听起来您达到了速率限制。
Your app can make 200 calls per hour per user in aggregate.
您可以检查 dashboard 以查看在这些情况下您是否达到了速率限制。
您可能达到了 Facebook API 的限制。要限制请求,您应该在前一个请求的某个时间间隔后发送每个请求。您没有包括迭代所有用户的位置,但我怀疑您可能会循环执行此操作,如果您使用 setTimeout
以 200 毫秒的固定延迟延迟每个请求,那么您将同时完成所有请求与之前一样的时间 - 仅晚 200 毫秒。
您可以做的是:
- 您可以使用 setTimeout 并为每个请求添加可变延迟(不推荐)
- 您可以使用异步模块的
series
或 parallelLimit
(使用回调)
- 您可以将 Bluebird 的
Promise.mapSeries
或 Promise.map
与 concurrency
限制一起使用(使用承诺)
不推荐使用 1,因为它仍然是即发即弃(除非你增加更多的复杂性)并且你仍然有并发过多和超过限制的风险,因为你只控制何时请求开始,而不是有多少未完成的请求。
2 和 3 大部分相同,但在使用回调或承诺方面有所不同。在您的示例中,您使用的是回调,但您的 callSendAPI
没有自己的回调,如果您希望选项 2 起作用,它应该这样做 - 或者,如果您想要选项,它应该 return 一个承诺3 上班。
有关详细信息,请参阅文档:
- https://caolan.github.io/async/docs.html#parallelLimit
- https://caolan.github.io/async/docs.html#series
- http://bluebirdjs.com/docs/api/promise.map.html
- http://bluebirdjs.com/docs/api/promise.mapseries.html
当然还有更多方法可以做到,但这些是最直接的。
理想情况下,如果您想充分利用每小时 200 个请求的限制,那么您应该自己对请求进行排队,并按照与该限制相对应的特定时间间隔发出请求。有时,如果您在一个小时内没有执行很多请求,那么您就不需要延迟,但有时您会。您在这里真正应该做的是将所有请求集中排队,并以与已经用完的部分相对应的时间间隔清空队列,达到您应该自己跟踪的限制 - 但这可能很棘手。
我的数据库中有 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);
如果 he/she 遇到类似的错误,有人可以提供帮助吗?
已编辑
我使用的 Messenger 平台支持发送 API 的高调用率,并且不限于 200 次调用。
听起来您达到了速率限制。
Your app can make 200 calls per hour per user in aggregate.
您可以检查 dashboard 以查看在这些情况下您是否达到了速率限制。
您可能达到了 Facebook API 的限制。要限制请求,您应该在前一个请求的某个时间间隔后发送每个请求。您没有包括迭代所有用户的位置,但我怀疑您可能会循环执行此操作,如果您使用 setTimeout
以 200 毫秒的固定延迟延迟每个请求,那么您将同时完成所有请求与之前一样的时间 - 仅晚 200 毫秒。
您可以做的是:
- 您可以使用 setTimeout 并为每个请求添加可变延迟(不推荐)
- 您可以使用异步模块的
series
或parallelLimit
(使用回调) - 您可以将 Bluebird 的
Promise.mapSeries
或Promise.map
与concurrency
限制一起使用(使用承诺)
不推荐使用 1,因为它仍然是即发即弃(除非你增加更多的复杂性)并且你仍然有并发过多和超过限制的风险,因为你只控制何时请求开始,而不是有多少未完成的请求。
2 和 3 大部分相同,但在使用回调或承诺方面有所不同。在您的示例中,您使用的是回调,但您的 callSendAPI
没有自己的回调,如果您希望选项 2 起作用,它应该这样做 - 或者,如果您想要选项,它应该 return 一个承诺3 上班。
有关详细信息,请参阅文档:
- https://caolan.github.io/async/docs.html#parallelLimit
- https://caolan.github.io/async/docs.html#series
- http://bluebirdjs.com/docs/api/promise.map.html
- http://bluebirdjs.com/docs/api/promise.mapseries.html
当然还有更多方法可以做到,但这些是最直接的。
理想情况下,如果您想充分利用每小时 200 个请求的限制,那么您应该自己对请求进行排队,并按照与该限制相对应的特定时间间隔发出请求。有时,如果您在一个小时内没有执行很多请求,那么您就不需要延迟,但有时您会。您在这里真正应该做的是将所有请求集中排队,并以与已经用完的部分相对应的时间间隔清空队列,达到您应该自己跟踪的限制 - 但这可能很棘手。