2016-02-25 60 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),然後重新安排自身,除非隊列爲空。