Kestrel と Node.js は両方とも libuv に基づいています。
Node.jsは イベントループ を使用していると正確に述べていますが、Kestrelの場合、またはIISのようなスレッドプーリング/リクエストキューを使用しているかどうかはわかりませんか?
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
ASP.Net Core 2.0用に更新されました。 pokeが指すように、サーバーはホスティングとトランスポートに分割されており、libuvはトランスポート層に属します。 libuv ThreadCount
は独自のLibuvTransportOptions
に移動され、UseLibuv()
extメソッドを使用してWebホストビルダーで個別に設定されます。
Githubで LibuvTransportOptions
クラスをチェックすると、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;
このオプションは、WebホストビルダーのUseLibuv
の呼び出しで設定できます。例えば:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseLibuv(opts => opts.ThreadCount = 4)
.UseStartup<Startup>()
.Build();
ASP.NET Core 1.Xでは、Libuv configはkestrelサーバーの一部でした:
Githubリポジトリで KestrelServerOptions
クラスを確認すると、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;
このオプションは、UseKestrel
の呼び出しで、たとえば新しい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();
}
ソースコードを掘り下げる:
KestrelThreads
)が KestrelEngine
で作成されているのがわかります。ThreadPool
メソッドを呼び出して、libuvスレッドの代わりにCLRスレッドプールでコードを実行できるようにします。 (ThreadPool.QueueUserWorkItem
を使用)。プールはデフォルトで 最大32Kスレッド に変更されているようです configを介して 。Frame<TContext>
は、要求を処理するために実際のアプリケーション(ASP.Net Coreアプリケーションなど)に委任します。だから、IOに複数のlibuvイベントループを使用していると言えます。実際の作業は、CLRスレッドプールを使用して、標準ワーカースレッドでマネージコードで実行されます。
これについてのより信頼できるドキュメントを見つけたいと思います( 公式ドキュメント 詳細は述べません)。私が見つけた最高のものは、Damian Edwardsが channel 9 でケストレルについて話していることです。 12分ごろ、彼は説明します。
さらに、クイック検索が返されました:
スレッドはトランスポート固有です。 Daniel JG の回答に記載されているlibuvトランスポート(2.0のデフォルト)では、マシン上の論理プロセッサの数に基づいたイベントループがいくつかあり、その値を設定することでオーバーライドできますオプション。デフォルトでは、各接続は特定のスレッドにバインドされ、そのスレッドですべてのIO操作が行われます。ユーザーがIOスレッドをブロックしないことを信用していないため、ユーザーコードはスレッドプールスレッドで実行されます。これらのスレッドプールスレッド(つまり、HttpResponse.WriteAsync
)でIO呼び出しを行うと、kestrelはソケットをバインドした適切なIOスレッドにマーシャリングする作業を行います。典型的な要求フローは次のようになります。
[ネットワークからの読み取り]スレッドプールへのディスパッチ-> [http解析]、[ミドルウェアパイプラインの実行]呼び出し->ユーザー作業をIOスレッドへのキューイング[ネットワークへの書き込み]
もちろん、あなたはいつでもケストレルがプロであることを伝えることができ、IOスレッドをブロックしてコードを実行することはありません。しかし、私は自分が何をしているのかを知らない限り、そうはしないだろう(そして、私は知らない:D)。