Quelques milliers de requêtes par minute représentent un gros load, et la seule façon de le faire correctement, est de contrôler et de limiter le nombre maximum de threads pouvant être exécutés à tout moment.
Comme il n'y a pas beaucoup d'informations publiées sur la façon dont vous avez implémenté cela. Je vais couvrir quelques circonstances possibles.
Il est temps d'expérimenter...
Les constantes :
- Éléments à traiter :
- 50 par seconde , ou en d'autres termes...
- 3 000 par minute , et une autre façon de voir les choses...
- 180 000 par heure
Les variables :
-
Taux de transfert de données :
-
La quantité de données que vous pouvez transférer par seconde jouera un rôle, peu importe ce que nous faisons, et cela variera tout au long de la journée en fonction de l'heure de la journée.
La seule chose que nous pouvons faire est de déclencher plus de requêtes de différents processeurs pour répartir le poids du trafic que nous renvoyons.
-
-
Puissance de traitement :
-
Je suppose que vous avez ceci dans un
WebJob
au lieu d'avoir cela codé à l'intérieur du site MVC, c'est lui-même. C'est très inefficace et ne convient pas à l'objectif que vous essayez d'atteindre. En utilisant un WebJob, nous pouvons mettre en file d'attente éléments de travail à traiter par d'autresWebJobs
. La file d'attente en question est la Azure Queue Stockage .
-
Les problèmes :
- Nous essayons d'effectuer 50 transactions par seconde. Par conséquent, chaque transaction devrait être effectuée en moins d'une seconde si nous utilisions 50 threads. Notre temps mort de 45 secondes ne sert à rien à ce stade.
- Nous nous attendons à ce que 50 threads s'exécutent simultanément et se terminent tous en moins d'une seconde, chaque seconde, sur un seul processeur. (J'exagère un point ici, juste pour souligner un point... mais imaginez télécharger 50 fichiers texte chaque seconde. Le traiter, puis essayer de le renvoyer à un collègue dans l'espoir qu'il sera même prêt à attrape-le)
- Nous devons mettre en place une logique de nouvelle tentative, si après 3 tentatives l'élément n'est pas traité, il doit être replacé dans la file d'attente. Idéalement, nous devrions donner plus de temps au serveur pour répondre qu'une seule seconde à chaque échec, disons que nous lui avons donné une pause de 2 secondes au premier échec, puis 4 secondes, puis 10, cela augmentera considérablement les chances que nous persistions / récupérer les données dont nous avions besoin.
- Nous supposons que notre MongoDb peut gérer ce nombre de requêtes par seconde. Si vous ne l'avez pas déjà fait, commencez à chercher des moyens de l'étendre, le problème n'est pas dans le fait qu'il s'agit d'un MongoDb, la couche de données aurait pu être n'importe quoi, c'est le fait que nous faisons ce nombre de demandes de une source unique qui sera la cause la plus probable de vos problèmes.
La solution :
- Configurer un
WebJob
et nommez-leEnqueueJob
. CeWebJob
aura un seul but, mettre en file d'attente les éléments de travail à traiter dans leQueue Storage
. - Créer un
Queue Storage Container
nomméWorkItemQueue
, cette file d'attente servira de déclencheur à l'étape suivante et lancera nos opérations d'évolution. - Créer un autre
WebJob
nomméDequeueJob
. CeWebJob
aura également un seul but, retirer les éléments de travail de laWorkItemQueue
et envoyez les requêtes à votre magasin de données. - Configurer le
DequeueJob
pour tourner une fois qu'un élément a été placé dans laWorkItemQueue
, démarrez 5 threads distincts sur chacun et tant que la file d'attente n'est pas vide, retirez les éléments de travail de chaque thread et tentez d'exécuter le travail retiré de la file d'attente.- Tentative 1, en cas d'échec, attendez et réessayez.
- Tentative 2, en cas d'échec, attendez et réessayez.
- Tentative 3, en cas d'échec, remettre l'élément en file d'attente dans
WorkItemQueue
- Configurez votre site Web pour qu'il s'adapte automatiquement à x quantité de processeurs (notez que votre site Web et vos tâches Web partagent les mêmes ressources)
Voici une courte vidéo de 10 minutes qui donne un aperçu de la façon d'utiliser les stockages de file d'attente et les travaux Web.
Modifier :
Une autre raison pour laquelle vous pouvez obtenir ces erreurs peut également être due à deux autres facteurs, encore une fois causés par le fait qu'il se trouve dans une application MVC...
Si vous compilez l'application avec le DEBUG
attribut appliqué mais poussant le RELEASE
version à la place, vous pourriez rencontrer des problèmes en raison des paramètres de votre web.config
, sans le DEBUG
, une application Web ASP.NET exécutera une demande pendant un maximum de 90 secondes, si la demande prend plus de temps que cela, elle éliminera la demande.
Pour augmenter le délai d'attente à plus de 90 secondes vous devrez changer le [httpRuntime][3]
propriété dans votre web.config
...
<!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
L'autre chose dont vous devez être conscient est les paramètres de délai d'expiration de la demande de votre navigateur> application Web, je dirais que si vous insistez pour conserver le code dans MVC au lieu de l'extraire et de le mettre dans un WebJob, alors vous pouvez utiliser le code suivant pour envoyer une requête à votre application Web et compenser le délai d'expiration de la requête.
string html = string.Empty;
string uri = "http://google.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Timeout = TimeSpan.FromMinutes(5);
using (HttpWebResponse response = (HttpWebResonse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
}