web-dev-qa-db-ja.com

KestrelはNode.jsのようなリクエストの処理に単一のスレッドを使用していますか?

KestrelNode.js は両方とも libuv に基づいています。

Node.jsは イベントループ を使用していると正確に述べていますが、Kestrelの場合、またはIISのようなスレッドプーリング/リクエストキューを使用しているかどうかはわかりませんか?

Webサーバーの背後にあるチョウゲンボウ

Kestrel behind a web server

Node.jsイベントループ

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

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();
    }
    

ソースコードを掘り下げる:

  • Libuvリスナースレッド(または KestrelThreads )が KestrelEngine で作成されているのがわかります。
  • 一部の場所では ThreadPool メソッドを呼び出して、libuvスレッドの代わりにCLRスレッドプールでコードを実行できるようにします。 (ThreadPool.QueueUserWorkItemを使用)。プールはデフォルトで 最大32Kスレッド に変更されているようです configを介して
  • Frame<TContext> は、要求を処理するために実際のアプリケーション(ASP.Net Coreアプリケーションなど)に委任します。

だから、IOに複数のlibuvイベントループを使用していると言えます。実際の作業は、CLRスレッドプールを使用して、標準ワーカースレッドでマネージコードで実行されます。

これについてのより信頼できるドキュメントを見つけたいと思います( 公式ドキュメント 詳細は述べません)。私が見つけた最高のものは、Damian Edwardsが channel 9 でケストレルについて話していることです。 12分ごろ、彼は説明します。

  • libuvはシングルスレッドイベントループモデルを使用します
  • ケストレルは複数のイベントループをサポートしています
  • ケストレルはlibuvイベントループでIOのみを処理します
  • IO以外のすべての作業(解析、フレーミングなど、HTTPに関連するものを含む)は、標準の.netワーカースレッドのマネージコードで実行されます。

さらに、クイック検索が返されました:

  • Kestrelでのスレッドプーリングについて話すDavid Fowler here 。また、要求がASP.Net Coreのスレッド間でジャンプする可能性があることも確認します。 (以前のバージョンと同様)
  • これ blogpost ケストレルが出てきたときに見る
  • この 質問 ASP.Net Coreでのスレッドの管理方法について。
75
Daniel J.G.

スレッドはトランスポート固有です。 Daniel JG の回答に記載されているlibuvトランスポート(2.0のデフォルト)では、マシン上の論理プロセッサの数に基づいたイベントループがいくつかあり、その値を設定することでオーバーライドできますオプション。デフォルトでは、各接続は特定のスレッドにバインドされ、そのスレッドですべてのIO操作が行われます。ユーザーがIOスレッドをブロックしないことを信用していないため、ユーザーコードはスレッドプールスレッドで実行されます。これらのスレッドプールスレッド(つまり、HttpResponse.WriteAsync)でIO呼び出しを行うと、kestrelはソケットをバインドした適切なIOスレッドにマーシャリングする作業を行います。典型的な要求フローは次のようになります。

[ネットワークからの読み取り]スレッドプールへのディスパッチ-> [http解析]、[ミドルウェアパイプラインの実行]呼び出し->ユーザー作業をIOスレッドへのキューイング[ネットワークへの書き込み]

もちろん、あなたはいつでもケストレルがプロであることを伝えることができ、IOスレッドをブロックしてコードを実行することはありません。しかし、私は自分が何をしているのかを知らない限り、そうはしないだろう(そして、私は知らない:D)。

39
davidfowl