我有 1000 条记录需要访问速率受限的 API 端点。我希望在任何给定时间只对 URL 进行 5 次调用,这样我就不会同时发出 1000 个请求。我怎样才能做到这一点?我有以下内容:
var Promise = require("bluebird");
var geocoder = Promise.promisifyAll(require('geocoder'));
var fs = require('fs');
var async = require('async');
var parse = require('csv-parse/lib/sync');
var inputFile = './myaddresses.txt'
var file = fs.readFileSync(inputFile, "utf8");
var records = parse(file, {columns: true});
var promises = [];
for(var i = 0; i < records.length; i++) {
var placeName = records[i]['Place Name'];
promises.push(geocoder.geocodeAsync(placeName));
}
Promises.all(promises).then(function(result) {
result.forEach(function(geocodeResponse) {
console.log(geocodeResponse);
})
}
为了限制同时进行的并发请求数量,我建议使用 BluebirdPromise.map()
它提供了并发选项。它将为您执行以下所有操作:
- 迭代你的数组
- 将并发请求数限制为您将并发选项设置为的值
- 将所有结果按顺序收集到最终结果数组中
以下是您将如何使用它:
const Promise = require('bluebird');
Promise.map(records, r => {
let placeName = r['Place Name'];
return geocoder.geocodeAsync(placeName));
}, {concurrency: 5}).then(results => {
// all results here
}).catch(err => {
// process error here
});
注意:速率限制通常与并发请求数并不严格相同。限制并发请求的数量将使您更有可能保持在速率限制之下,但并不能保证这一点。有特定的速率限制模块可以更直接地管理速率限制。
您可以使用 Bluebird 为每个请求添加延迟.delay()
.
const Promise = require('bluebird');
Promise.map(records, r => {
let placeName = r['Place Name'];
return geocoder.geocodeAsync(placeName)).delay(500);
}, {concurrency: 5}).then(results => {
// all results here
}).catch(err => {
// process error here
});
处理某些类型的速率限制的经典算法称为漏桶算法 https://en.wikipedia.org/wiki/Leaky_bucket.
如果您的限制是 50 个请求/秒,那么您只需确保并发数乘以延迟值决不允许超过 50 个/秒。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)