我正在一个需要通过API提出请求的项目中工作。请求返回有关支持票据的数据,但问题是我有大约500张票来获取数据,每个票据需要一个请求。为了加快请求,我尝试构建一个异步例程,同时生成许多请求。但是,由于我集成的API具有每秒10个请求的速率限制器,因此一些例程得到答案"限制超过"。如果我按顺序提出请求,则需要大约5分钟。
那样的话,有人在那个任务中有我的小费吗?我尝试了一些解决方案,如NodeJS的速率限制器,但它只是同时生成10个请求,并且没有提供任何类型的错误处理或在请求失败时重试。
关于语言,没有限制,项目是用NodeJS编写的,但也有一些python代码,并没有问题来集成另一种语言。
答案 0 :(得分:1)
这样的事情并不难以自己创造,而且它可以为您提供所需的灵活性。
有一些奇特的方法,比如跟踪每个的开始和完成时间,并检查你是否在第二个时间内发送了10个。
系统可能还将其限制为10个活动请求(即,您无法启动100个请求,每秒10个,并让它们全部处理)。
如果你假设这一点,我会一次说启动10,然后让它们完成,然后启动下一批。您也可以启动10,然后每次完成后再启动1。您可以将其视为" thread pool"。
您可以使用一个简单的变量轻松跟踪此信息,以跟踪调用的次数。然后,只需检查每秒进行多少次呼叫(以避免1秒限制),如果有可用的"线程",则触发更多新请求。
看起来像这样:
const threadLimit = 10;
const rateLimit = 1000; // ms
let activeThreads = 0;
const calls = new Array(100).fill(1).map((_, index) => index); // create an array 0 through 99 just for an example
function run() {
if (calls.length == 0) {
console.log('complete');
return;
}
// threadLimit - activeThreads is how many new threads we can start
for (let i = 0; i < threadLimit - activeThreads && calls.length > 0; i++) {
activeThreads++; // add a thread
call(calls.shift())
.then(done);
}
setInterval(run, rateLimit);
}
function done(val) {
console.log(`Done ${val}`);
activeThreads--; // remove a thread
}
function call(val) {
console.log(`Starting ${val}`);
return new Promise(resolve => waitToFinish(resolve, val));
}
// random function to simulate a network call
function waitToFinish(resolve, val) {
const done = Math.random() < .1; // 10% chance to finish
done && resolve(val)
if (!done) setInterval(() => waitToFinish(resolve, val), 10);
return done;
}
run();
&#13;
基本上,run()
只会根据限制和完成的数量启动许多新线程。然后,它只是每秒重复一次这个过程,尽可能地添加新的过程。
您可能需要使用threadLimit
和rateLimit
值,因为大多数速率限制系统实际上都不会让您上升到极限并且不会释放它一旦完成。