Ejecutar 1000 solicitudes de modo que solo 10 ejecute a la vez

Con node.js quiero http.get un número de urls remotos de una manera que solo se ejecutan 10 (o n) a la vez.

También quiero volver a intentar una solicitud si se produce una excepción local (m veces), pero cuando el código de estado devuelve un error (5XX, 4XX, etc.), la solicitud cuenta como válida.

Esto es muy difícil para mí envolver mi cabeza.

Problemas:

  1. No se puede intentar capturar http.get ya que es asíncrono.
  2. Necesita una forma de volver a intentar una solicitud en caso de error.
  3. Necesito algún tipo de semáforo que realice un seguimiento del recuento de solicitudes actualmente activo.
  4. Cuando todas las solicitudes hayan finalizado, quiero obtener la lista de todas las URL de solicitud y los códigos de estado de respuesta en una lista que deseo ordenar / agrupar / manipular, por lo que debo esperar a que todas las solicitudes finalicen.

Parece que para cada problema asíncrono se recomiendan promesas, pero al final anido demasiadas promesas y rápidamente se vuelven incurables.

Hay muchas formas de abordar las 10 solicitudes que se ejecutan a la vez.

  1. Biblioteca asíncrona: use la biblioteca asíncrona con el método .parallelLimit() donde puede especificar la cantidad de solicitudes que desea ejecutar al mismo tiempo.

  2. Biblioteca de promesas de Bluebird : use la biblioteca de promesas de Bluebird y la biblioteca de request para envolver su http.get() en algo que pueda devolver una promesa y luego use Promise.map() con una opción de concurrencia establecida en 10 .

  3. Codificado manualmente: codifique sus solicitudes manualmente para iniciar 10 y luego cada vez que se complete una, inicie otra.

En todos los casos, tendrá que escribir manualmente un código de rebash y, al igual que con todos los códigos de rebash, tendrá que decidir con mucho cuidado qué tipos de errores reintenta, qué tan pronto los reintenta, cuánto retrocede entre los bashs de rebash y cuándo. eventualmente renunciar a (todas las cosas que no han especificado).

Otras respuestas relacionadas:

¿Cómo hacer millones de solicitudes http paralelas desde la aplicación nodejs?

Millones de solicitudes, 10 a la vez – ejemplo codificado manualmente


Mi método preferido es con Bluebird y promete. Incluyendo el rebash y la recostackción de resultados en orden, podría verse algo como esto:

 const request = require('request'); const Promise = require('bluebird'); const get = Promise.promisify(request.get); let remoteUrls = [...]; // large array of URLs const maxRetryCnt = 3; const retryDelay = 500; Promise.map(remoteUrls, function(url) { let retryCnt = 0; function run() { return get(url).then(function(result) { // do whatever you want with the result here return result; }).catch(function(err) { // decide what your retry strategy is here // catch all errors here so other URLs continue to execute if (err is of retry type && retryCnt < maxRetryCnt) { ++retryCnt; // try again after a short delay // chain onto previous promise so Promise.map() is still // respecting our concurrency value return Promise.delay(retryDelay).then(run); } // make value be null if no retries succeeded return null; }); } return run(); }, {concurrency: 10}).then(function(allResults) { // everything done here and allResults contains results with null for err URLs }); 

La forma más sencilla es usar una biblioteca async , tiene un método .parallelLimit que hace exactamente lo que necesita.