はじめに

ASP.NET CoreをIISで動かしたときに、Httpリクエストがどういう流れでアプリケーションコードまで到達するのか気になり調べてみました。

前提

IISのバージョンによってアーキテクチャが異なります。
IIS 7.0以降について調べた内容となります。※私の手元の環境はIIS 10.0となります
ホスティングモデルはASP.NET Core 3.0以降ではデフォルトの「インプロセスホスティング」となります。

  • IIS 7.0以降
  • ASP.NET Core
  • インプロセスホスティング

IISのアーキテクチャ

IISの構成要素

IISの構成要素は、このサイトより引用

  • HTTP プロトコルスタック (HTTP.sys) HTTP.sys は、端的に言うと HTTP/HTTPS 用の通信ドライバです。HTTP コネクションの管理、HTTP ヘッダー解析、URL/URI/IRI の解析、HTTP リクエストのログ機能、キャッシュ機能、および、SSL 機能等、多くの機能が HTTP.sys に搭載されています。
  • Windows プロセスアクティブ化サービス (Windows Process Activation Service : WAS) WAS は、ワーカープロセスを管理するサービスです。実行中のワーカープロセスの健常性を監視しています。また、WASは、構成情報の読み取りなども行います。
  • World Wide Web 発行サービス (World Wide Web Publishing Service : W3SVC) W3SVCは、HTTP.sys 及び WAS と通信を行い、HTTP.sys に構成情報を提供します。また、W3SVC は、Web サイトのパフォーマンス監視も行います。
  • 構成ストア 構成ストアは、XML 形式の設定ファイル群を表す仮想的なストアです。IIS 全体の構成情報は、 IIS のサーバーレベルの構成ファイルである、applicationHost.config に格納されています。この中には IIS の構成が含まれます。また、アプリケーションの構成は、ご存じの通り、各アプリケーションの web.config に含まれています。
  • ワーカープロセス ワーカープロセスは、要求の処理と応答の生成を行うプロセスです。

ASP.NET CoreのWebアプリケーションはワーカプロセスで実行されます。

Httpリクエストの処理フロー

IISがHttpリクエストを処理する流れは、下記となります。
さきほどのサイトを参考に書きました。
イメージ

  1. HTTP要求がクライアントブラウザからサーバーへ到着します。HTTP.sys が要求を受け取ります。要求が応答キャッシュのエントリに一致した場合、HTTP.sys はキャッシュ応答をカーネル モードから直接送信します。(上図の赤ライン)
  2. HTTP.sys が要求の送信先アプリケーションの構成情報が登録されているか確認をし、登録されていなかった場合は、HTTP.sys は W3SVC に問い合わせを行います。
  3. W3SVC は、WAS へ要求を渡します。(以降、上図の黄色ライン)
  4. WASは、IIS のサーバーレベルの構成情報である、applicationHost.config を構成ストアから取得します。
  5. WASは、要求されたアプリケーションプール内のワーカープロセスを確認します。ワーカープロセスが存在しない場合は、そのアプリケーションプール用のワーカープロセスを起動します。
  6. WASより、アプリケーションプールの情報や構成情報を W3SVC に渡します。
  7. W3SVC は、WASから受け取った構成情報に基づき、HTTP.sys へ設定および更新の通知をします。
  8. HTTP.sysは、その通知を基に、アプリケーション用のキューを作成してから、適切なワーカープロセスに要求を転送します。
  9. 要求を受け取ったワーカープロセスは、要求処理を開始します。
  10. 要求処理パイプラインのそれぞれの処理を行い、ワーカープロセスは、要求の処理結果を HTTP.sys へ返します。
  11. HTTP.sys がクライアントに応答を送信します。

動作確認

環境

  • Windows Server 2019 試用版
  • IIS 10.0
  • Hyper-V 10.0

リスナーの確認

IISを立ち上げると、
ファイアウォールの受信規則にTCP:80番ポートの許可が追加されます。
イメージ

コマンドプロンプトでnetstat -anoを実行するとTCP:80番ポートで待ち受けていることが分かります。

C:\Users\Administrator>netstat -ano
  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:80             0.0.0.0:0              LISTENING       4
  TCP         [::]:80                [::]:0                 LISTENING       4


プロセス/サービスの確認

カーネルモード

TCP:80番ポートで待ち受けているPID4のプロセスをタスクマネージャーで確認するとWindowsカーネルC:\Windows\System32\ntoskrnl.exeだと分かります。
イメージ

さらに、ProcessExplorerでPID4のプロセスを見ると下記を呼び出してることが分かります。
イメージ

  • Interrupts(Hardware Interrupts and DPCs)
  • smss.exe(Windows セッション マネージャー)C:\Windows\System32\smss.exe

おそらくですが、InterruptsからTCPIP.sysC:\Windows\System32\drivers\tcpip.sys経由でHTTP.sysC:\Windows\System32\drivers\http.sysが呼び出される?!のではないかと思ってます。

ユーザーモード

タスクマネージャーのサービスを見ると、W3SVC, WASがあり、PID868で実行されていることが分かります。 イメージ

コマンドプロンプトでも確認ができ、tasklist /svcを実行するとW3SVC, WASがホストされているsvchost.exeC:\Windows\System32\svchost.exe、PIDが分かります。

C:\Users\Administrator>tasklist /svc
イメージ名                     PID サービス
========================= ======== ============================================
svchost.exe                    868 W3SVC, WAS

注意として、このサイトより引用

svchost.exe というプロセスは Windows で各種サービスをホストするための汎用プロセスです。 従って svchost.exe という名前でホストされているサービスは多数ありますので、svchost.exe というプロセスが見えたからと言って、 IIS ではありませんので注意してください。


Httpリクエストを投げて、
ProcessExplorerでPID868のsvchost.exeを見るとワーカプロセス(w3wp.exec:\Windows\System32\inetsrv\w3wp.exe)を呼び出してることが分かります。
イメージ
タスクマネージャーでPID4976のw3wp.exeを見ると、
イメージ
IISのアプリケーションプール名と一致します。
イメージ


ワーカプロセスは、ブラウザを閉じても(TCPのコネクションが切れても)実行し続けます。
ワーカプロセスは、アプリケーションプールの設定にしたがい(デフォルトでは20分で)終了します。
イメージ
イベントログWindowsログ/システムを見るとWASがワーカプロセスを終了させたことが分かります。 イメージ

結果

IISの構成要素が動作していることが分かりました。

参考サイト