web-dev-qa-db-fra.com

Gestion des threads dans asp.net core / kestrel

Je dépanne les problèmes de performances/d'évolutivité avec une application asp.net que nous avons migrée vers asp.net core 2.0. Notre application est hébergée sur Azure en tant que service d'application et tombe trop facilement avec un trafic modéré.

Une chose qui me laisse perplexe est de savoir comment plusieurs demandes simultanées sont traitées. D'après ce que j'ai lu ici , Kestrel utilise plusieurs boucles d'événements pour gérer vos demandes. Mais le code utilisateur réel est géré sur le pool de threads .net ( c'est d'ici ).

Donc, à titre expérimental - j'ai créé une nouvelle application MVC asp.net core 2.0 et ajouté une méthode d'action plutôt méchante:

    [AllowAnonymous]
    public ActionResult Wait1()
    {
        System.Threading.Tasks.Task.Delay(1000).Wait();
        return new StatusCodeResult((int)HttpStatusCode.OK);
    }     

Maintenant, quand je pousse ceci vers Azure, je m'attends à ce que si j'envoie disons 100 demandes en même temps, alors je devrais être OK, car 100 requêtes sonne comme une charge mineure, non? Et l'attente se produira sur les threads du pool de threads, non?

Donc - je fais juste cela et j'obtiens des résultats plutôt médiocres - échantillon surligné en rouge:

enter image description here

Hmm, pas ce à quoi je m'attendais, environ 50 secondes par requête ... Si toutefois je change la fréquence pour que les requêtes soient espacées d'une seconde, le temps de réponse est correct - retour à un peu plus de 1000 ms comme vous vous en doutez. Il semble que si je passe plus de 30 requêtes en même temps, ça commence à en souffrir, ce qui me semble un peu faible.

Donc - je me rends compte que ma méthode d'action méchante bloque, mais je m'attendais à ce qu'elle bloque sur un thread de pool de threads, et donc être capable de faire face à plus de mes 30.

S'agit-il d'un comportement attendu - et dans l'affirmative, s'agit-il simplement de s'assurer qu'aucun travail lié aux E/S n'est effectué sans utiliser de code asynchrone?

11
Matt Roberts

S'agit-il d'un comportement attendu - et dans l'affirmative, s'agit-il simplement de s'assurer qu'aucun travail lié aux E/S n'est effectué sans utiliser de code asynchrone?

D'après mon expérience, il semble que ce soit le comportement attendu. Nous pourrions obtenir une réponse de cette blog .

Supposons maintenant que vous exécutez votre application ASP.Net sur IIS et que votre serveur Web dispose d'un total de quatre processeurs. Supposons qu'à tout moment donné, il y ait 100 demandes à traiter. Par Par défaut, le runtime créerait quatre threads, qui seraient disponibles pour traiter les quatre premières demandes. Comme aucun thread supplémentaire ne sera ajouté tant que 500 millisecondes ne se seront pas écoulées, les 96 autres requêtes devront attendre dans la file d'attente. Après 500 millisecondes se sont écoulées, un nouveau thread est créé.

Comme vous pouvez le voir, il faudra 100 * 500 ms intervalles pour rattraper la charge de travail.

C'est une bonne raison d'utiliser programmation asynchrone . Avec la programmation asynchrone, les threads ne sont pas bloqués pendant le traitement des demandes, de sorte que les quatre threads seraient libérés presque immédiatement.

Je vous recommande d'utiliser du code asynchrone pour améliorer les performances.

public async Task<ActionResult> Wait1()
{
    await Task.Delay(TimeSpan.FromSeconds(15));
    return new StatusCodeResult((int)HttpStatusCode.OK);
}

J'en trouve aussi un autre SO thread , vous pouvez y faire référence.

6
Tom Sun