1
votes

Comment limiter la demande par seconde dans la tâche Async C #

J'écris une application qui interagit avec Azure Cosmos DB. J'ai besoin de valider 30 000 enregistrements dans CosmosDB dans une session. Parce que j'ai utilisé .NET Core, je ne peux donc pas utiliser de DLL BulkInsert. Donc, j'utilise la boucle Foreach pour insérer dans CosmosDB. Mais je vois trop de requêtes par seconde et cela surcharge la limite RU par CosmosDB.

foreach(item in listNeedInsert){
      await RequestInsertToCosmosDB(item);
}

Je veux mettre en pause pour chaque boucle lorsque le nombre de requêtes atteint 100. Après 100 requêtes. foreach continuera.


9 commentaires

veuillez consulter stackoverflow.com/questions/23921210/…


wait attend déjà des tâches en cours d'exécution. Cela ne les démarre pas et ne contrôle pas leur exécution.


Si vous souhaitez limiter le nombre d'insertions à N par seconde, ajoutez un délai dans la boucle pour vous assurer que pas plus de N appels peuvent être effectués par seconde avec wait Task.Delay (...); .


Pouvez-vous savoir par programme si les inserts sont terminés? si vous le faites alors, ce que vous devez faire, c'est trouver un compteur, puis quand il atteint 100 requêtes, attendez que les insertions se terminent, puis continuez


Pouvez-vous définir une contrainte - soit je ne dois démarrer que n requêtes par seconde, et / ou seules n requêtes peuvent être exécutées à un moment donné? Quelle que soit la contrainte qui vous pousse à faire cela, je coderais ceci pour l'adapter spécifiquement à cette contrainte. Si vous visez un nombre arbitraire comme 100, que se passe-t-il s'ils s'exécutent toujours trop vite? Sera-ce prévisible et cohérent? Si le besoin est de limiter les demandes par seconde, faites-le spécifiquement. Ne faites rien d'autre et espérez que cela fonctionnera.


Une autre façon de formuler ceci - vous posez deux questions différentes. Le titre indique que vous souhaitez limiter les requêtes par seconde, mais vous dites ensuite que vous souhaitez faire une pause toutes les 100. Cela signifie moins requêtes par seconde, mais ce n'est pas la même chose que limiter les requêtes par seconde. Voici peut-être ce que vous voulez: stackoverflow.com/questions/10806951/...


Le SDK .NET pour ComsosDB se désactive automatiquement et réessaye lorsqu'il utilise trop de RU. Y a-t-il une raison pour laquelle ce comportement ne fonctionne pas pour vous?


En plus de ce que Stephen a dit, la limitation manuelle ne fonctionnera que si vous n'avez qu'une seule instance de votre application en cours d'exécution.Dans ce cas, je ne sais pas si Cosmos DB est la technologie qu'il vous faut car son argument de vente est sa capacité d'échelle et sa distribution mondiale.


J'ai trouvé une solution à mon problème. Merci à vous tous.


3 Réponses :


0
votes

Vous pouvez définir un délai toutes les 100 itérations

int i = 1;
foreach(item in listNeedInsert)
{
      await RequestInsertToCosmosDB(item);
      if (i % 100 == 0)
      {
          i = 0;
          await Task.Delay(100); // Miliseconds
      }
      i++;
}


3 commentaires

Cela retarde également la première itération.


Merci pour l'indice que je l'ai corrigé


Maintenant, après le premier délai, il sera retardé à chaque 99e itération ..!



2
votes

Vous pouvez partitionner la liste et attendre les résultats:

var tasks = new List<Task>();

foreach(item in listNeedInsert)
{
    var task = RequestInsertToCosmosDB(item);
    tasks.Add(task);

    if(tasks.Count == 100)
    {
        await Task.WhenAll(tasks);
        tasks.Clear();
    }
}

// Wait for anything left to finish
await Task.WhenAll(tasks);

Chaque fois que vous avez 100 tâches en cours d'exécution, le code attendra qu'elles se terminent toutes avant d'exécuter le dernier lot. p>


1 commentaires

100 requêtes simultanées sont bien trop nombreuses pour que la base de données puisse les traiter efficacement. J'essaierais quelque chose dans la gamme à un chiffre. Essayez d'expérimenter différents nombres pour voir ce qui fonctionne le mieux. Si vous voulez encore plus d'efficacité, utilisez SemaphorSlim et son mécanisme de limitation intégré.



0
votes

Si vous voulez vraiment maximiser l'efficacité et que vous ne pouvez pas effectuer de mises à jour groupées, envisagez d'utiliser SemaphorSlim dans cet article:

Limitation des tâches asynchrones

Marteler une base de données de taille moyenne avec 100 requêtes simultanées à la fois n'est pas une bonne idée car elle n'est pas équipée pour gérer ce type de débit. Vous pouvez essayer de jouer avec un nombre de limitation différent et voir ce qui est optimal, mais je suppose que c'est dans la plage à un chiffre.

Si vous voulez faire quelque chose de rapide et sale, vous pouvez probablement utiliser la solution de Sean. Mais je définirais le nombre de tâches à 5 au départ, et non à 100.


0 commentaires