Le jour où Dodo IS s'est arrêté. Script asynchrone

Bonjour, Habr! Chaque SRE de notre équipe rêvait de dormir paisiblement la nuit. Les rêves deviennent réalité. Dans cet article, je parlerai de cela et de la façon dont nous atteignons les performances et la stabilité de notre système Dodo IS.


Une série d'articles sur l'effondrement du système Dodo IS * :

1. Le jour où Dodo IS s'est arrêté. Script synchrone.
2. Le jour où Dodo IS s'est arrêté. Script asynchrone.

* Les matériaux ont été écrits sur la base de ma performance à DotNext 2018 à Moscou .
Dans un article précédent, nous avons examiné les problèmes de blocage de code dans le paradigme du multitâche préemptif. Il était supposé qu'il était nécessaire de réécrire le code de blocage sur async / wait. Nous l'avons donc fait. Parlons maintenant des problèmes survenus lorsque nous avons fait cela.

Nous introduisons le terme Concurrence


Avant d'arriver à async, vous devez saisir le terme accès simultané.
Dans la théorie des files d'attente, la concurrence est le nombre de clients qui sont actuellement à l'intérieur du système. La concurrence est parfois confondue avec le parallélisme, mais en réalité, ce sont deux choses différentes.
Pour ceux qui découvrent Concurrency pour la première fois, je recommande la vidéo de Rob Pike . La simultanéité, c'est quand nous traitons beaucoup de choses en même temps, et le parallélisme, c'est quand nous faisons beaucoup de choses en même temps.

Dans les ordinateurs, peu de choses se produisent en parallèle. Une telle chose est le calcul sur plusieurs processeurs. Le degré de parallélisme est limité par le nombre de threads CPU.

En fait, Threads fait partie du concept de multitâche préemptif, l'une des façons de modéliser la concurrence dans un programme lorsque nous nous appuyons sur le système d'exploitation dans la question Concurrence. Ce modèle reste utile tant que nous comprenons que nous traitons spécifiquement du modèle de concurrence, et non de la concurrence.

Async / Wait est un sucre syntaxique pour State Machine, un autre modèle de concurrence utile qui peut s'exécuter dans un environnement à thread unique. Il s'agit essentiellement du multitâche coopératif - le modèle lui-même ne prend pas du tout en compte le parallélisme. En combinaison avec le multithreading, nous obtenons un modèle au-dessus d'un autre et la vie est très compliquée.

Comparaison des deux modèles


Comment cela a fonctionné dans le modèle multitâche préemptif


Disons que nous avons 20 threads et 20 requêtes en traitement par seconde. L'image montre un pic - 200 demandes dans le système en même temps. Comment cela pourrait-il arriver:

  • les demandes pourraient être regroupées si 200 clients cliquaient sur un bouton en même temps;
  • le ramasse-miettes pourrait arrêter les demandes pendant plusieurs dizaines de millisecondes;
  • les demandes peuvent être retardées dans n'importe quelle file d'attente si le proxy prend en charge la file d'attente.

Il existe de nombreuses raisons pour lesquelles les demandes pour une courte période se sont accumulées et sont regroupées en un seul ensemble. En tout cas, rien de terrible ne s'est produit, ils se tenaient dans la file d'attente Thread Pool et se sont lentement terminés. Il n'y a plus de pics, tout se passe comme si de rien n'était.

Supposons que l'algorithme de pool de threads intelligent (et il y a des éléments d'apprentissage automatique là-bas) ait décidé qu'il n'y a jusqu'à présent aucune raison d'augmenter le nombre de threads. Le pool de connexions dans MySql est également de 20 car Threads = 20. En conséquence, nous n'avons besoin que de 20 connexions à SQL.



Dans ce cas, le niveau d'accès concurrentiel du serveur du point de vue du système externe = 200. Le serveur a déjà reçu ces demandes, mais ne les a pas encore terminées. Cependant, pour une application s'exécutant dans le paradigme Multithreading, le nombre de demandes simultanées est limité par la taille actuelle de Thread Pool = 20. Nous avons donc affaire au degré de concurrence = 20.

Comment tout fonctionne maintenant dans le modèle asynchrone




Voyons ce qui se passe dans une application exécutant async / wait avec la même charge et distribution des requêtes. Il n'y a pas de file d'attente avant de créer une tâche et la demande est immédiatement traitée. Bien sûr, Thread de ThreadPool est utilisé pendant une courte période et la première partie de la demande, avant de contacter la base de données, est exécutée immédiatement. Parce que Thread retourne rapidement à Thread Pool, nous n'avons pas besoin de beaucoup de Threads pour les traiter. Dans ce diagramme, nous n'affichons pas du tout le groupe de threads, il est transparent.



Qu'est-ce que cela signifie pour notre application? L'image extérieure est la même - le niveau de concurrence = 200. En même temps, la situation à l'intérieur a changé. Auparavant, les demandes étaient "encombrées" dans la file d'attente ThreadPool, maintenant le degré d'accès concurrentiel de l'application est également de 200, car nous n'avons aucune restriction de la part de TaskScheduler. Hourra! Nous avons atteint l'objectif asynchrone - l'application "faire face" à presque tous les degrés de concurrence!

Conséquences: dégradation non linéaire du système


L'application est devenue transparente du point de vue de la concurrence, donc maintenant la concurrence est projetée sur la base de données. Nous avons maintenant besoin d'un pool de connexions de la même taille = 200. La base de données est le CPU, la mémoire, le réseau, le stockage. C'est le même service avec ses problèmes, comme n'importe quel autre. Plus nous essayons d'exécuter de requêtes en même temps, plus elles s'exécutent lentement.

À pleine charge sur la base de données, au mieux, le temps de réponse se dégrade linéairement: vous avez donné deux fois plus de requêtes, il a commencé à fonctionner deux fois plus lentement. Dans la pratique, en raison de la concurrence entre les requêtes, une surcharge se produira nécessairement et il se peut que le système se dégrade de façon non linéaire.

Pourquoi cela se produit-il?


Raisons de la deuxième commande:

  • La base de données doit maintenant être conservée simultanément dans la mémoire de la structure de données pour répondre à davantage de demandes;
  • Désormais, la base de données doit servir de plus grandes collections (ce qui est algorithmiquement désavantageux).

Raison du premier ordre:


Au final, async se bat contre des ressources limitées et ... gagne! La base de données échoue et commence à ralentir. À partir de cela, le serveur augmente encore la concurrence, et le système ne peut plus sortir de cette situation avec honneur.

Syndrome de mort subite du serveur


Parfois, une situation intéressante se produit. Nous avons un serveur. Il travaille pour lui comme ça, tout est en ordre. Il y a suffisamment de ressources, même avec une marge. Ensuite, nous recevons soudainement un message des clients que le serveur ralentit. Nous regardons le graphique et voyons qu'il y a eu une certaine augmentation de l'activité des clients, mais maintenant tout est normal. Penser à une attaque DOS ou à une coïncidence. Maintenant, tout semble aller bien. Seulement maintenant, le serveur continue d'être stupide, et tout est plus difficile jusqu'à ce que les délais d'attente commencent à affluer. Après un certain temps, un autre serveur qui utilise la même base de données commence également à se plier. Une situation familière?

Pourquoi le système est-il mort?


Vous pouvez essayer d'expliquer cela par le fait qu'à un moment donné, le serveur a reçu un nombre maximal de demandes et s'est «cassé». Mais nous savons que la charge a été réduite, et le serveur ne s'est pas amélioré pendant très longtemps, jusqu'à ce que la charge disparaisse complètement.

La question rhétorique: le serveur était-il censé tomber en panne en raison d'une charge excessive? Le font-ils?

Nous simulons une situation de plantage du serveur


Ici, nous n'analyserons pas les graphiques d'un vrai système de production. Au moment de la panne du serveur, nous ne pouvons souvent pas obtenir un tel calendrier. Le serveur manque de ressources CPU et, par conséquent, il ne peut pas écrire de journaux ni fournir de mesures. Sur les diagrammes au moment de la catastrophe, une rupture dans tous les graphiques est souvent observée.

Les SRE devraient être capables de produire des systèmes de surveillance moins sujets à cet effet. Les systèmes qui, dans n'importe quelle situation, fournissent au moins certaines informations, et en même temps, sont capables d'analyser des systèmes post mortem en utilisant des informations fragmentaires. À des fins éducatives, nous utilisons une approche légèrement différente dans cet article.

Essayons de créer un modèle qui fonctionne mathématiquement comme un serveur sous charge. Ensuite, nous étudierons les caractéristiques du serveur. Nous ignorons la non-linéarité des serveurs réels et simulons une situation où une décélération linéaire se produit lorsque la charge dépasse le nominal. Deux fois plus de demandes que nécessaire - nous servons deux fois plus lentement.

Cette approche permettra:

  • réfléchissez à ce qui se passera au mieux;
  • prendre des mesures précises.

Navigation planifiée:

  • bleu - le nombre de demandes au serveur;
  • vert - réponses du serveur;
  • jaune - délais d'attente;
  • gris foncé - demandes qui ont été supprimées sur les ressources du serveur car le client n'a pas attendu de réponse de délai d'attente. Parfois, un client peut signaler cela au serveur en se déconnectant, mais en général, un tel luxe peut être techniquement impossible, par exemple, si le serveur effectue un travail lié au processeur, sans coopération avec le client.




Pourquoi le graphique de demande du client (bleu dans le diagramme) s’est-il révélé être le cas? En règle générale, le calendrier des commandes dans nos pizzerias croît en douceur le matin et diminue le soir. Mais nous observons trois pics sur le fond de la courbe uniforme habituelle. Cette forme du graphique n'a pas été choisie par hasard pour le modèle, mais plutôt. Le modèle est né lors de l'enquête sur un incident réel avec le serveur du centre de contact de la pizzeria en Russie lors de la Coupe du monde.

Cas "Coupe du monde"


Nous nous sommes assis et avons attendu plus de commandes. Préparés pour le championnat, les serveurs pourront désormais passer un test de résistance.

Premier pic - les fans de football vont regarder le championnat, ils ont faim et achètent de la pizza. Au cours du premier semestre, ils sont occupés et ne peuvent pas commander. Mais les gens qui sont indifférents au football le peuvent, donc sur la carte tout se passe comme d'habitude.

Et puis la première moitié se termine, et le deuxième pic arrive. Les fans sont devenus nerveux, affamés et ont passé trois fois plus de commandes qu'au premier pic. La pizza s'achète à un prix terrible. Ensuite, la deuxième moitié commence, et encore pas à la pizza.

Pendant ce temps, le serveur du centre de contact commence à se plier lentement et à servir les demandes de plus en plus lentement. Le composant système, dans ce cas, le serveur Web du centre d'appels, est déstabilisé.

Le troisième pic arrivera à la fin du match. Les fans et le système attendent une pénalité.

Nous analysons les raisons de la panne du serveur


Qu'est-il arrivé? Le serveur peut contenir 100 requêtes conditionnelles. Nous comprenons qu'il est conçu pour cette puissance et ne le supportera plus. Un pic arrive, qui en soi n'est pas si grand. Mais la zone grise de la concurrence est beaucoup plus élevée.

Le modèle est conçu de manière à ce que la concurrence soit numériquement égale au nombre de commandes par seconde, donc visuellement sur le graphique, elle devrait être de la même échelle. Cependant, il est beaucoup plus élevé car il s'accumule.

Nous voyons ici une ombre du graphique - ce sont des demandes qui ont commencé à retourner au client, exécutées (indiquées par la première flèche rouge). L'échelle de temps est conditionnelle pour voir le décalage temporel. Le deuxième pic a déjà assommé notre serveur. Il s'est écrasé et a commencé à traiter quatre fois moins de demandes que d'habitude.



Dans la seconde moitié du graphique, il est clair que certaines demandes étaient toujours exécutées au début, mais des taches jaunes sont ensuite apparues - les demandes ont complètement cessé.



Encore une fois tout le programme. On peut voir que la concurrence se déchaîne. Une énorme montagne apparaît.



Habituellement, nous avons analysé des mesures complètement différentes: la vitesse à laquelle la demande a été traitée, le nombre de demandes par seconde. Nous ne regardons même pas la concurrence, nous n'avons même pas pensé à cette métrique. Mais en vain, car c'est précisément cette quantité qui montre le mieux le moment de défaillance du serveur.

Mais d'où venait une montagne si énorme? Le plus gros pic de charge est passé depuis longtemps!

Little Law


La loi de Little régit la concurrence.

L (nombre de clients dans le système) = λ (vitesse de leur séjour) ∗ W (temps qu'ils passent à l'intérieur du système)

C'est une moyenne. Cependant, notre situation évolue dramatiquement, la moyenne ne nous convient pas. Nous différencierons cette équation, puis intégrerons. Pour ce faire, regardez le livre de John Little, qui a inventé cette formule, et voyez l'intégrale là.



Nous avons le nombre d'entrées dans le système et le nombre de ceux qui quittent le système. La demande arrive et part lorsque tout est terminé. Vous trouverez ci-dessous une région de croissance du graphique correspondant à la croissance linéaire de la concurrence.



Il y a peu de demandes vertes. Ce sont ceux qui sont réellement mis en œuvre. Les bleus sont ceux qui viennent. Entre temps, nous avons le nombre habituel de demandes, la situation est stable. Mais la concurrence continue de croître. Le serveur ne fera plus face à cette situation. Cela signifie qu'il va bientôt tomber.

Mais pourquoi la concurrence augmente-t-elle? Nous regardons l'intégrale de la constante. Rien ne change dans notre système, mais l'intégrale ressemble à une fonction linéaire qui ne fait que croître.

Allons-nous jouer?


L'explication avec les intégrales est compliquée si vous ne vous souvenez pas des mathématiques. Ici, je propose de me réchauffer et de jouer au jeu.

Numéro de jeu 1


Prérequis : le serveur reçoit des requêtes, chacune nécessite trois périodes de traitement sur la CPU. La ressource CPU est répartie également entre toutes les tâches. Ceci est similaire à la façon dont les ressources CPU sont consommées pendant le multitâche préemptif. Le nombre dans la cellule signifie la quantité de travail restant après cette mesure. Pour chaque étape conditionnelle, une nouvelle demande arrive.

Imaginez que vous ayez reçu une demande. Il ne reste que 3 unités de travail, à la fin de la première période de traitement, il reste 2 unités.

Dans la deuxième période, une autre demande est en couches, maintenant les deux CPU sont occupés. Ils ont effectué une unité de travail pour les deux premières requêtes. Il reste à compléter respectivement 1 et 2 unités pour la première et la deuxième demande.

Maintenant, la troisième demande est arrivée et le plaisir commence. Il semblerait que la première demande aurait dû être terminée, mais pendant cette période, trois demandes partagent déjà la ressource CPU, de sorte que le degré d'achèvement pour les trois demandes est désormais fractionné à la fin de la troisième période de traitement:



Encore plus intéressant! La quatrième demande est ajoutée, et maintenant le degré de concurrence est déjà de 4, car les quatre demandes nécessitaient une ressource au cours de cette période. Pendant ce temps, la première demande à la fin de la quatrième période est déjà terminée, elle ne passe pas à la période suivante et il reste 0 tâches pour le CPU.

La première demande étant déjà terminée, résumons pour lui: elle a duré un tiers de plus que prévu. On a supposé que la longueur de chaque tâche horizontalement idéalement = 3, selon la quantité de travail. Nous le marquons en orange, signe que nous ne sommes pas entièrement satisfaits du résultat.



La cinquième demande arrive. Le degré de concurrence est toujours de 4, mais nous voyons que dans la cinquième colonne, le travail restant est plus global. En effet, il reste plus de travail dans la quatrième colonne que dans la troisième.

Nous continuons encore trois périodes. En attente de réponses.
- Serveur, bonjour!
- ...



"Votre appel est très important pour nous ..."



Eh bien, est finalement venue la réponse à la deuxième demande. Les temps de réponse sont deux fois plus longs que prévu.



Le degré de concurrence a déjà triplé, et rien ne présage que la situation va s'améliorer. Je n'ai pas dessiné plus loin, car le temps de réponse à la troisième requête ne rentrera plus dans l'image.

Notre serveur est entré dans un état indésirable, dont il ne sortira jamais seul. Game over

Qu'est-ce qui caractérise l'état GameOver du serveur?


Les demandes sont accumulées indéfiniment en mémoire. Tôt ou tard, la mémoire cessera tout simplement. De plus, avec une augmentation d'échelle, la surcharge du processeur pour l'entretien de diverses structures de données augmente. Par exemple, le pool de connexions doit désormais suivre les délais d'expiration pour plus de connexions, le garbage collector doit maintenant revérifier plus d'objets sur le tas, etc.

Explorer toutes les conséquences possibles de l'accumulation d'objets actifs n'est pas le but de cet article, mais même une simple accumulation de données en RAM suffit déjà pour remplir le serveur. De plus, nous avons déjà vu que le serveur client projette ses problèmes d'accès concurrentiel sur le serveur de base de données et sur d'autres serveurs qu'il utilise en tant que client.

La chose la plus intéressante: maintenant, même si vous soumettez une charge inférieure au serveur, il ne récupérera toujours pas. Toutes les demandes se termineront par un délai d'expiration et le serveur consommera toutes les ressources disponibles.

Et à quoi nous attendions-nous réellement?! Après tout, nous avons sciemment donné au serveur une quantité de travail qu'il ne pouvait pas gérer.

Lorsque vous traitez avec une architecture de système distribué, il est utile de réfléchir à la façon dont les gens ordinaires résolvent ces problèmes. Prenez, par exemple, une boîte de nuit. Il cessera de fonctionner si trop de personnes y entrent. Le videur résout le problème simplement: il regarde combien de personnes sont à l'intérieur. Un à gauche - en lance un autre. Un nouvel invité viendra apprécier la taille de la file d'attente. Si la file d'attente est longue, il rentrera chez lui. Et si vous appliquez cet algorithme au serveur?



Jouons à nouveau.

Numéro de jeu 2


Prérequis : Encore une fois, nous avons deux processeurs, les mêmes tâches de 3 unités, arrivant à chaque période, mais maintenant nous allons définir le videur, et les tâches seront intelligentes - s'ils voient que la longueur de la file d'attente est de 2, ils rentrent immédiatement à la maison.





La troisième demande est venue. Dans cette période, il fait la queue. Il a le numéro 3 à la fin de la période. Il n'y a pas de nombres fractionnaires dans les résidus, car deux CPU effectuent deux tâches, une pour une période.

Bien que nous ayons trois demandes en couches, le degré de concurrence à l'intérieur du système = 2. La troisième est dans la file d'attente et ne compte pas.



Le quatrième est venu - la même image, bien que plus de travail ait déjà été accumulé.


...
...

Dans la sixième période, la troisième demande a été traitée avec un troisième décalage, et le degré de concurrence est déjà = 4.



Le degré de concurrence a doublé. Elle ne peut plus grandir, car nous avons clairement interdit cela. Avec une vitesse maximale, seules les deux premières demandes ont été traitées - celles qui sont venues en premier au club, alors qu'il y avait suffisamment d'espace pour tout le monde.

Les demandes jaunes étaient dans le système plus longtemps, mais elles étaient en ligne et n'ont pas retardé la ressource CPU. Par conséquent, ceux qui étaient à l'intérieur s'amusaient. Cela pourrait continuer jusqu'à ce qu'un homme vienne et dise qu'il ne ferait pas la queue, mais plutôt qu'il rentrerait chez lui. Il s'agit d'une demande ayant échoué:



La situation peut être répétée à l'infini, tandis que le temps d'exécution de la requête reste au même niveau - exactement deux fois plus longtemps que nous le souhaiterions.



Nous voyons qu'une simple restriction sur le niveau de concurrence élimine le problème de viabilité du serveur.

Comment augmenter la viabilité du serveur via la limite de niveau d'accès concurrentiel


Vous pouvez écrire vous-même le «videur» le plus simple. Ci-dessous, le code utilisant le sémaphore. Il n'y a pas de limite à la longueur de la ligne extérieure. Le code est uniquement à des fins d'illustration, pas besoin de le copier.

const int MaxConcurrency = 100; SemaphoreSlim bulkhead = new SemaphoreSlim(MaxConcurrency, MaxConcurrency); public async Task ProcessRequest() { if (!await bulkhead.WaitAsync()) { throw new OperationCanceledException(); } try { await ProcessRequestInternal(); return; } finally { bulkhead.Release(); } } 

Pour créer une file d'attente limitée, vous avez besoin de deux sémaphores. Pour cela, la bibliothèque Polly , que Microsoft recommande, convient. Faites attention au motif de cloison. Traduit littéralement par «cloison» - un élément structurel qui permet au navire de ne pas couler. Pour être honnête, je pense que le terme videur est mieux adapté. L'important est que ce modèle permette au serveur de survivre dans des situations désespérées.

Tout d'abord, nous extrayons tout ce qui est possible sur le banc de charge du serveur jusqu'à ce que nous déterminions le nombre de demandes qu'il peut contenir. Par exemple, nous avons déterminé qu'il est de 100. Nous avons mis une cloison.

De plus, le serveur ne sautera que le nombre requis de demandes, le reste sera mis en file d'attente. Il serait sage de choisir un nombre légèrement plus petit pour qu'il y ait une marge. Je n'ai pas de recommandation toute faite à ce sujet, car il y a une forte dépendance au contexte et à la situation spécifique.

  1. Si le comportement du serveur dépend de manière stable de la charge en termes de ressources, alors ce nombre peut approcher la limite.
  2. Si le support est soumis à des fluctuations de charge, un nombre plus prudent doit être choisi, en tenant compte de la taille de ces fluctuations. De telles fluctuations peuvent se produire pour diverses raisons, par exemple, l'environnement de performance avec GC est caractérisé par de petits pics de charge sur le CPU.
  3. Si le serveur effectue des tâches périodiques selon un calendrier, cela doit également être pris en compte. Vous pouvez même développer une cloison adaptative qui calculera le nombre de requêtes pouvant être envoyées simultanément sans dégradation du serveur (mais cela dépasse déjà le cadre de cette étude).

Expériences de requête


Jetez un œil à ce post-mortem en dernier, nous ne le verrons plus.

Tout ce tas gris est sans équivoque en corrélation avec le crash du serveur. Gray est la mort du serveur. Disons simplement le couper et voir ce qui se passe. Il semble qu'un certain nombre de demandes rentreront chez elles, ne seront tout simplement pas satisfaites. Mais combien?

100 à l'intérieur, 100 à l'extérieur



Il s'est avéré que notre serveur a commencé à vivre très bien et amusant. Il laboure constamment à puissance maximale. Bien sûr, lorsqu'un pic survient, cela le met à la porte, mais pas pour longtemps.

Inspiré par le succès, nous allons essayer de nous assurer qu'il ne rebondit pas du tout. Essayons d'augmenter la longueur de la file d'attente.

100 à l'intérieur, 500 à l'extérieur




Ça s'est amélioré, mais la queue a grandi. Ce sont les demandes qui sont exécutées longtemps après.

100 à l'intérieur, 1000 à l'extérieur


Puisque quelque chose s'est amélioré, essayons de l'amener au point d'absurdité. Résolvons la longueur de la file d'attente 10 fois plus que ce que nous pouvons servir simultanément:



Si nous parlons de la métaphore du club et des videurs, cette situation n'est guère possible - personne ne veut attendre plus longtemps à l'entrée que passer du temps dans le club. Nous ne prétendrons pas non plus qu'il s'agit d'une situation normale pour notre système.

Il vaut mieux ne pas servir le client du tout que le tourmenter sur le site ou dans l'application mobile en chargeant chaque écran pendant 30 secondes et en gâchant la réputation de l'entreprise. Il vaut mieux dire immédiatement et honnêtement à une petite partie des clients que nous ne pouvons plus les servir. Sinon, nous servirons tous les clients plusieurs fois plus lentement, car le graphique montre que la situation persiste pendant un certain temps.

Il existe un risque supplémentaire: d'autres composants système peuvent ne pas être conçus pour un tel comportement de serveur et, comme nous le savons déjà, la concurrence est projetée sur les clients.

Par conséquent, nous revenons à la première option «100 pour 100» et réfléchissons à la manière de dimensionner nos capacités.

Gagnant - 100 à l'intérieur, 100 à l'extérieur




¯ \ _ (ツ) _ / ¯

Avec ces paramètres, la plus grande dégradation de l'exécution est exactement 2 fois la «valeur nominale». Dans le même temps, c'est une dégradation de 100% du temps d'exécution des requêtes.

Si votre client est sensible au temps d'exécution (et cela est généralement vrai à la fois avec les clients humains et les clients serveur), vous pouvez alors envisager de réduire davantage la longueur de la file d'attente. Dans ce cas, nous pouvons prendre un certain pourcentage de la concurrence interne, et nous saurons avec certitude que le service ne se dégrade pas dans le temps de réponse de plus de ce pourcentage en moyenne.

En fait, nous n'essayons pas de créer une file d'attente, nous essayons de nous protéger des fluctuations de charge. Ici, tout comme dans le cas de la détermination du premier paramètre de la cloison (quantité à l'intérieur), il est utile de déterminer quelles fluctuations de la charge le client peut provoquer. Nous saurons donc dans quels cas, grosso modo, nous manquerons le profit d'un service potentiel.

Il est encore plus important de déterminer quelles fluctuations de latence peuvent supporter d'autres composants du système interagissant avec le serveur. Nous saurons donc que nous tirons vraiment le maximum du système existant sans risquer de perdre complètement le service.

Diagnostic et traitement


Nous traitons la concurrence non contrôlée avec l'isolement de cloison.
Cette méthode, comme les autres discutées dans cette série d'articles, est commodément implémentée par la bibliothèque Polly .

L'avantage de la méthode est qu'il sera extrêmement difficile de déstabiliser un composant individuel du système en tant que tel. Le système acquiert un comportement très prévisible en termes de temps pour les demandes réussies et des chances beaucoup plus élevées pour les demandes complètes réussies.

Cependant, nous ne résolvons pas tous les problèmes. Par exemple, le problème d'une alimentation insuffisante du serveur. Dans cette situation, vous devez évidemment décider de «larguer le ballast» en cas de saut de charge, que nous avons jugé excessif.

D'autres mesures que notre étude ne traite pas peuvent inclure, par exemple, la mise à l'échelle dynamique.

Source: https://habr.com/ru/post/fr461081/


All Articles