Exécutez 1000 demandes de sorte que seulement 10 s'exécute à la fois

Avec node.js, je souhaite http.get un certain nombre d'URL distantes d'une manière que seulement 10 (ou n) s'exécute à la fois.

Je souhaite également réessayer une demande si une exception survient localement (m fois), mais lorsque le code d'état renvoie une erreur (5XX, 4XX, etc.), la demande compte comme valide.

C'est vraiment difficile pour moi de m'enrouler.

Problèmes:

  1. Ne peut pas essayer d'attraper http.get car il est asynchrone.
  2. Besoin d'un moyen de réessayer une demande d'échec.
  3. J'ai besoin d'une sorte de sémaphore qui surveille le nombre de requêtes actuellement actif.
  4. Lorsque toutes les demandes ont terminé, je souhaite obtenir la liste de toutes les URL de demande et les codes d'état de la réponse dans une liste que je souhaite trier / grouper / manipuler, alors j'ai besoin d'attendre que toutes les demandes soient terminées.

On dirait que, pour chaque problème asynchrone, des promesses sont recommandées, mais je finis par nicher trop de promesses et cela devient rapidement indéfectible.

Il existe de nombreuses façons d'aborder les 10 requêtes en cours d'exécution à la fois.

  1. Bibliothèque asynchrone: utilisez la bibliothèque asynchrone avec la méthode .parallelLimit() où vous pouvez spécifier le nombre de requêtes que vous souhaitez exécuter en même temps.

  2. Bluebird Promise Library – Utilisez la bibliothèque Bluebird prometteur et la bibliothèque de request pour envelopper votre http.get() dans quelque chose qui peut retourner une promesse, puis utilisez Promise.map() avec une option de concurrence définie sur 10 .

  3. Codé manuellement – Codez vos requêtes manuellement pour démarrer 10, puis chaque fois que l'une est terminée, commencez une autre.

Dans tous les cas, vous devrez rédiger manuellement un nouveau code de réinitialisation et, comme avec tout le nouveau code, vous devrez décider avec précaution quels types d'erreurs vous essayez, combien de temps vous les réessayez, combien vous renversez-vous entre les tentatives de réessayez et lorsque vous Finissent par abandonner (toutes choses que vous n'avez pas spécifiées).

Autres réponses connexes:

Comment faire des millions de demandes parallèles http de l'application nodejs?

Million de demandes, 10 à la fois – exemple codé manuellement


Ma méthode préférée est avec Bluebird et des promesses. Y compris la réinscription et la collecte des résultats dans l'ordre, cela pourrait ressembler à ceci:

 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 manière simple consiste à utiliser la bibliothèque async , elle possède une méthode .parallelLimit qui fait exactement ce dont vous avez besoin.