2016-02-25 105 views
0

我试图回写处理请求到特定API的最终功能,但是此API有一些限制性配额,特别是对于请求/秒。我想创建API抽象层,能够延迟功能的执行,如果有太多的请求/ s,因此它的工作原理是这样的:在时间段内执行n次的延迟函数执行(API调用)

  1. 新的请求到达时(把它简单 - 被调用的库法)
  2. 检查这一要求可以马上执行的,根据给定的极限(请求/秒)
  3. 如果它不能被执行,延迟执行,直到下一个可用时刻
  4. 如果此时新的请求到达,进一步延迟其执行或将其放在一些执行队列上

我在等待队列长度方面没有任何限制。请求是带有node.js回调的函数调用,作为用数据响应的最后一个参数。

我想为每个请求添加延迟,这将等于请求之间的最小可能时隙(表示为最小毫秒/请求),但它可能有点低效(始终在发送响应之前延迟功能)。

你知道任何图书馆或简单的解决方案,可以为我提供这样的功能吗?

+0

如果是我,我不会做任何排队的请求,而是告诉客户端请求无法处理。 –

+0

它纯粹是后端功能,因此每个请求都必须作为更大进程的一部分来完成 - 由于配额限制,它只能被延迟。 – SzybkiSasza

+2

429太多请求[RFC6585](https://tools.ietf.org/html/rfc6585) – Fozi

回答

0

这个问题(和最好的)的确切答案来自API文档本身。我们使用它几个月,它完美地解决了我的问题。

在这种情况下,最好的办法是利用JS处理异步代码的可能性,或者自己编写简单的退避或者使用其中一个很好的库来使用。因此,如果偶然发现任何API限制(例如配额,5xx等),则应该使用退避来递归地再次运行查询,但随着延迟的增加(更多关于退避的信息可以在这里找到:https://en.wikipedia.org/wiki/Exponential_backoff)。而且,如果最终在给定的次数之后再次失败 - 优雅地返回关于API不可用的错误。

实施例下面使用(从https://www.npmjs.com/package/backoff截取):

var call = backoff.call(get, 'https://someaddress', function(err, res) { 
    console.log('Num retries: ' + call.getNumRetries()); 

    if (err) { 
     // Put your error handling code here. 
     // Called ONLY IF backoff fails to help 
     console.log('Error: ' + err.message); 
    } else { 
     // Put your success code here 
     console.log('Status: ' + res.statusCode); 
    } 
}); 

/* 
* When to retry. Here - 503 error code returned from the API 
*/ 
call.retryIf(function(err) { return err.status == 503; }); 

/* 
* This lib offers two strategies - Exponential and Fibonacci. 
* I'd suggest using the first one in most of the cases 
*/ 
call.setStrategy(new backoff.ExponentialStrategy()); 

/* 
* Info how many times backoff should try to post request 
* before failing permanently 
*/ 
call.failAfter(10); 

// Triggers backoff to execute given function 
call.start(); 

存在用于的NodeJS许多退避库,利用的是第二上述任一无极式,回调式或甚至事件式的退避处理(例如提到的那些)。如果您了解回退算法本身,它们非常易于使用。由于退避参数可以存储在配置中,如果退避失败太频繁,可以对其进行调整以获得更好的结果。

0

保存上次请求的时间戳。

只要你有一个新传入的请求,检查是否从那时起最小时间间隔时,如果没有,就把函数在一个队列,然后安排工作(除非已定):

setTimeout(
    processItemFromQueue, 
    (lastTime + minInterval - new Date()).getTime() 
) 

processItemFromQueue从队列的前端获取作业(shift),然后重新安排自身,除非队列为空。