usando una nodejs node hacer example cómo create crear con como node.js asynchronous request throttle

node.js - una - Acelerar y hacer cola en las solicitudes API por límite por segundo



mongodb node js api (6)

Aquí está mi solución, use una request-promise biblioteca request-promise o axios y envuelva la llamada en esta promesa.

var Promise = require("bluebird") // http://stackoverflow.com/questions/28459812/way-to-provide-this-to-the-global-scope#28459875 // http://stackoverflow.com/questions/27561158/timed-promise-queue-throttle module.exports = promiseDebounce function promiseDebounce(fn, delay, count) { var working = 0, queue = []; function work() { if ((queue.length === 0) || (working === count)) return; working++; Promise.delay(delay).tap(function () { working--; }).then(work); var next = queue.shift(); next[2](fn.apply(next[0], next[1])); } return function debounced() { var args = arguments; return new Promise(function(resolve){ queue.push([this, args, resolve]); if (working < count) work(); }.bind(this)); }

Estoy usando mikeal/request para hacer llamadas API. Una de las API que uso con más frecuencia (la API de Shopify). Recientemente saqué un nuevo límite de llamadas , estoy viendo errores como:

Exceeded 6.0 calls per second for api client. Slow your requests or contact support for higher limits.

Ya he recibido una actualización, pero independientemente de la cantidad de ancho de banda que tenga, tengo que dar cuenta de esto. Una gran mayoría de las solicitudes a la API de Shopify están dentro de las funciones async.map() , que async.map() bucle de solicitudes asíncronas y reúnen los cuerpos.

Estoy buscando alguna ayuda, tal vez una biblioteca que ya exista, que cubra el módulo de solicitud y realmente bloquee, suspenda, acelere, asigne, administre, las muchas solicitudes simultáneas que se activan de forma asincrónica y limítelas a decir 6 solicitudes a la vez No tengo ningún problema para trabajar en un proyecto como este si no existe. Simplemente no sé cómo manejar este tipo de situación, y espero algún tipo de estándar.

Hice un boleto con mikeal/request .


El npm simple-rate-limiter paquete npm parece ser una muy buena solución a este problema.

Además, es más fácil de usar que node-rate-limiter async.queue y async.queue .

Aquí hay un fragmento que muestra cómo limitar todas las solicitudes a diez por segundo.

var limit = require("simple-rate-limiter"); var request = limit(require("request")).to(10).per(1000);


En el módulo asíncrono, esta función solicitada se cierra como "no se soluciona"

Existe una solución que usa el modelo leakybucket o token bucket, se implementa el módulo "limitador" npm como RateLimiter.

Vea el ejemplo aquí: https://github.com/caolan/async/issues/1314#issuecomment-263715550

var PromiseThrottle = require(''promise-throttle''); let RATE_PER_SECOND = 5; // 5 = 5 per second, 0.5 = 1 per every 2 seconds var pto = new PromiseThrottle({ requestsPerSecond: RATE_PER_SECOND, // up to 1 request per second promiseImplementation: Promise // the Promise library you are using }); let timeStart = Date.now(); var myPromiseFunction = function (arg) { return new Promise(function (resolve, reject) { console.log("myPromiseFunction: " + arg + ", " + (Date.now() - timeStart) / 1000); let response = arg; return resolve(response); }); }; let NUMBER_OF_REQUESTS = 15; let promiseArray = []; for (let i = 1; i <= NUMBER_OF_REQUESTS; i++) { promiseArray.push( pto .add(myPromiseFunction.bind(this, i)) // passing am argument using bind() ); } Promise .all(promiseArray) .then(function (allResponsesArray) { // [1 .. 100] console.log("All results: " + allResponsesArray); });

Salida:

myPromiseFunction: 1, 0.031 myPromiseFunction: 2, 0.201 myPromiseFunction: 3, 0.401 myPromiseFunction: 4, 0.602 myPromiseFunction: 5, 0.803 myPromiseFunction: 6, 1.003 myPromiseFunction: 7, 1.204 myPromiseFunction: 8, 1.404 myPromiseFunction: 9, 1.605 myPromiseFunction: 10, 1.806 myPromiseFunction: 11, 2.007 myPromiseFunction: 12, 2.208 myPromiseFunction: 13, 2.409 myPromiseFunction: 14, 2.61 myPromiseFunction: 15, 2.811 All results: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

Podemos ver claramente la tasa de salida, es decir, 5 llamadas por cada segundo.


Las otras soluciones no estaban a mi gusto. Investigando más, encontré promise-ratelimit que te da una API que simplemente puedes await :

var rate = 2000 // in milliseconds var throttle = require(''promise-ratelimit'')(rate) async function queryExampleApi () { await throttle() var response = await get(''https://api.example.com/stuff'') return response.body.things }

El ejemplo anterior garantizará que solo realice consultas a api.example.com cada 2000 ms como máximo . En otras palabras, la primera solicitud no esperará 2000 ms.


Me encontré con el mismo problema con varias API. AWS es famoso por la aceleración también.

Se pueden usar un par de enfoques. Usted mencionó la función async.map (). ¿Has probado async.queue() ? El método de cola debería permitirle establecer un límite sólido (como 6) y cualquier cantidad superior a esa cantidad se colocará en la cola.

Otra herramienta útil es oibackoff . Esa biblioteca le permitirá retrasar su solicitud si recibe un error del servidor e intenta nuevamente.

Puede ser útil ajustar las dos bibliotecas para asegurarse de que sus dos bases estén cubiertas: async.queue para asegurarse de que no exceda el límite, y oibackoff para asegurarse de tener otra oportunidad para recibir su solicitud si el servidor le dice Hubo un error.


Para una solución alternativa, utilicé el node-rate-limiter para ajustar la función de solicitud de esta manera:

var request = require(''request''); var RateLimiter = require(''limiter'').RateLimiter; var limiter = new RateLimiter(1, 100); // at most 1 request every 100 ms var throttledRequest = function() { var requestArgs = arguments; limiter.removeTokens(1, function() { request.apply(this, requestArgs); }); };