Kestrel et Node.js sont tous deux basés sur libuv .
Bien que Node.js indique exactement qu'il utilise ne boucle d'événement , je n'arrive pas à déterminer si tel est le cas pour Kestrel ou s'il utilise une file d'attente de pooling/de requêtes de threads comme IIS?
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
Mise à jour pour ASP.Net Core 2.0. Comme indiqué par poke, le serveur a été divisé entre hébergement et transport, libuv appartenant à la couche de transport. Libuv ThreadCount
a été déplacé vers son propre LibuvTransportOptions
et ils sont définis séparément dans votre générateur d’hébergeur Web avec la méthode UseLibuv()
ext:
Si vous cochez la classe LibuvTransportOptions
dans github, vous verrez une option ThreadCount
:
/// <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 à UseLibuv
, dans votre générateur hôte Web. Par exemple:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseLibuv(opts => opts.ThreadCount = 4)
.UseStartup<Startup>()
.Build();
Dans ASP.NET Core 1.X, la configuration de Libuv faisait partie du serveur Kestrel:
Si vous cochez la classe KestrelServerOptions
dans son dépôt github, vous verrez qu'il existe une option ThreadCount
:
/// <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 à UseKestrel
, par exemple dans une nouvelle application ASP.Net Core:
public static void Main(string[] args)
{
var Host = new WebHostBuilder()
.UseKestrel(opts => opts.ThreadCount = 4)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
Host.Run();
}
Creuser dans le code source:
KestrelThreads
) étant créés dans le KestrelEngine
ThreadPool
pour pouvoir exécuter du code dans le pool de threads CLR au lieu des threads libuv. (En utilisant ThreadPool.QueueUserWorkItem
). Le pool semble être configuré par défaut avec un maximum de 32K threads qui peut être modifié via config .Frame<TContext>
délégués à l'application réelle (comme une application ASP.Net Core) pour traiter la demande.On pourrait donc dire qu'il utilise plusieurs eventLops libuv pour IO. Le travail réel est effectué sur du code géré avec des threads de travail standard, à l'aide du pool de threads CLR.
J'aimerais trouver plus de documentation faisant autorité à ce sujet (les documents officiels ne donnent pas beaucoup de détails). Le meilleur que j'ai trouvé est Damian Edwards qui parle de Kestrel on channel 9 . Vers la minute 12, il explique:
De plus, une recherche rapide est revenue:
Le filetage est spécifique au transport. Avec le transport libuv (la valeur par défaut en 2.0) comme indiqué dans la réponse de Daniel JG , il existe un certain nombre de boucles d'événement basées sur le nombre de processeurs logiques sur la machine et qui peuvent être annulées en définissant la valeur sur le paramètre. options. Par défaut, chaque connexion est liée à un thread particulier et toutes les opérations IO ont lieu sur ce thread. Le code utilisateur est exécuté sur les threads du pool de threads car nous ne pensons pas que les utilisateurs ne bloqueront pas = IO threads. Lorsque vous effectuez IO appelle sur ces threads du pool de threads (c.-à-d. HttpResponse.WriteAsync
), Kestrel fait le travail pour le rediriger vers le thread IO) auquel le socket était lié. Un flux de requête typique ressemble à ceci:
[lire à partir du réseau] dispatch dans le pool de threads -> [analyse syntaxique http], [exécuter le pipeline de middleware] pour écrire -> mettre en file d'attente le travail de l'utilisateur sur le IO thread [écriture sur le réseau]
Bien sûr, vous pouvez toujours dire à Kestrel que vous êtes un professionnel et que vous ne bloquerez jamais le fil IO) et que vous exécutez votre code. Mais je ne le ferais pas à moins de savoir ce que je faisais (et je ne t: D).