75 votes

Kestrel utilise-t-il un seul thread pour traiter les requêtes comme Node.js?

Les deux Kestrel et Node.js sont basées sur libuv.

Alors que Node.js exactement états qu'il utilise une boucle, je n'arrive pas à trouver si tel est le cas de Kestrel, ou si elle utilise un fil de mise en commun / file d'attente des requêtes comme IIS?

Kestrel derrière un serveur web

Kestrel behind a web server

Node.js boucle d'événement

    ┌───────────────────────┐
 ┌─>│        timers         │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 │  │     I/O callbacks     │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 │  │     idle, prepare     │
 │  └──────────┬────────────┘      ┌───────────────┐
 │  ┌──────────┴────────────┐      │   incoming:   │
 │  │         poll          │<─────┤  connections, │
 │  └──────────┬────────────┘      │   data, etc.  │
 │  ┌──────────┴────────────┐      └───────────────┘
 │  │        check          │
 │  └──────────┬────────────┘
 │  ┌──────────┴────────────┐
 └──┤    close callbacks    │
    └───────────────────────┘

90voto

Daniel J.G. Points 23478

Mise à jour pour ASP.Net Core 2.0. Comme indiqué par poke, le serveur a été partagé entre l'hébergement et le transport, où libuv appartient à la couche de transport. Le libuv ThreadCount a été déplacé à son propre LibubTransportOptions et ils sont mis séparément dans votre hôte web builder avec l' UseLibuv() ext méthode:

  • Si vous cochez l' LibuvTransportOptions de la classe dans github, vous verrez ThreadCount option:

    /// <summary>
    /// The number of libuv I/O threads used to process requests.
    /// </summary>
    /// <remarks>
    /// Defaults to half of <see cref="Environment.ProcessorCount" /> rounded down and clamped between 1 and 16.
    /// </remarks>
    public int ThreadCount { get; set; } = ProcessorThreadCount;
    
  • L'option peut être définie dans l'appel d' UseLibuv, votre hôte web builder. Par exemple:

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseLibuv(opts => opts.ThreadCount = 4)
            .UseStartup<Startup>()                
            .Build();
    

Alors que dans ASP.NET Core 1.X, Libuv config faisait partie de la crécerelle serveur:

  • Si vous cochez l' KestrelServerOptions de la classe dans son dépôt github, vous verrez qu'il ya un ThreadCount option:

    /// <summary>
    /// The number of libuv I/O threads used to process requests.
    /// </summary>
    /// <remarks>
    /// Defaults to half of <see cref="Environment.ProcessorCount" /> rounded down and clamped between 1 and 16.
    /// </remarks>
    public int ThreadCount { get; set; } = ProcessorThreadCount;
    
  • L'option peut être définie dans l'appel d' UseKestrel, par exemple dans une nouvelle ASP.Net de Base de l'app:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel(opts => opts.ThreadCount = 4)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
    
        host.Run();
    }
    

En fouillant dans le code source:

  • Vous pouvez voir le libuv auditeur threads (ou KestrelThreads), créé à l' KestrelEngine
  • Certains endroits qui fera appel à la ThreadPool méthodes afin qu'ils puissent exécuter du code dans le CLR Pool de Threads au lieu de la libuv threads. (À l'aide d' ThreadPool.QueueUserWorkItem). La piscine semble être en défaut avec un max de 32K threads qui peuvent être modifiées via la config.
  • L' Frame<TContext> des délégués de l'application (comme un ASP.Net application de Base) pour le traitement de la demande.

Donc, on pourrait dire qu'il utilise plusieurs libuv eventloops pour IO. Le travail réel est fait sur le code géré avec le standard de threads de travail, à l'aide de la CLR pool de threads.

J'aimerais trouver plus de la documentation de référence sur ce sujet (Les docs officielles ne donnent pas beaucoup de détails). Le meilleur que j'ai trouvé est Damian Edwards parle Kestrel sur le canal 9. Autour de 12 minutes, il explique:

  • libuv utilise un thread unique boucle d'événement de modèle
  • Kestrel prend en charge de multiples boucle d'événement
  • Kestrel n'est que IO travail sur la libuv boucle d'événement
  • Tous les non IO travail (y compris tout ce qui est lié avec le protocole HTTP comme l'analyse, le cadrage, etc) est faite dans le code managé sur la norme .net threads de travail.

En outre, une recherche rapide est de retour:

  • David Fowler parler de mise en pool de threads dans la Crécerelle d' ici. Il confirme également qu'une demande peut peut encore sauter entre les threads ASP.Net de Base. (comme il était dans les versions précédentes)
  • Ce billet de blog en regardant Kestrel quand il est sorti
  • Cette question sur la façon dont les threads sont gérés dans ASP.Net de Base.

53voto

dfowler Points 16530

Le filetage de transport spécifiques. Avec le libuv de transport (la valeur par défaut dans la version 2.0) comme il est dit dans Daniel J. G.'s réponse il y a un certain nombre de boucle d'événement basé sur le nombre de processeurs logiques sur la machine et que c'est remplacée par la définition de la valeur sur les options. Par défaut, chaque connexion est lié à un fil et toutes les opérations d'e / s de prendre place sur ce thread. Le code de l'utilisateur est exécutée sur le pool de threads parce que nous n'avons pas confiance que les utilisateurs ne les empêcheront pas de IO threads. Quand vous faites IO appels sur ces threads du pool de threads (c - HttpResponse.WriteAsync), faucon crécerelle fait le travail de maréchal que le retour à la appropriée IO fil le socket a été lié. Une demande de type d'écoulement ressemble à ceci:

[ lire à partir de réseautage ] envoi de pool de threads -> [ http analyse ], [ exécuter middleware pipeline ] appel d'écriture -> mettre en file d'attente de travail des utilisateurs de l'e / s thread [ écrire réseau ]

Bien sûr, vous pouvez toujours dire kestrel vous êtes un pro et n'obstruez jamais les IO fil et exécuter votre code. Mais je ne voudrais pas, à moins que je savais ce que je faisais (et je n'en ai pas :D).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X