IIS オート スタート設定による ASP.NET Web アプリケーションの初回実行時のパフォーマンス向上

================

[2014/12/25 追記]

ASP.NET 開発に関連した動画学習コンテンツも用意しています。

ご参考に、ぜひご覧いただけると幸いです。

================

ASP.NET Web アプリケーションの初回実行時(IIS へ配置後の最初のリクエスト時)や、IIS アプリケーション プールがリサイクルされた後などは、ワーカープロセスの起動やアプリケーションの初期化処理(Application_Start メソッドの実行など)で、ページが表示されるまでに通常よりも時間がかかります。この初回実行時のリクエスト処理を高速化するため、ASP.NET 4 / IIS 7.5 から、アプリケーションのオートスタート(自動実行)機能が使用できるようになっています。

Auto-Start ASP.NET Applications (VS 2010 and .NET 4.0 Series) : ScottGu’s Blog

この機能を有効化するには、IIS の Application Initialization モジュールの有効化や、 アプリケーション プールの開始モードの変更(applicationHost.config の編集)などが必要ですが、オンプレミス環境では比較的容易に設定可能です。

● オンプレミス環境での IIS/ASP.NET オートスタートの有効化

1. Application Initialization モジュールの有効化

[Windows の機能の有効化または無効化] などで、IIS の Application Initialization モジュールを有効化します。(デフォルトでは無効になっています)

image

2. アプリケーション プールの開始モードの変更

IIS マネージャーで、対象のアプリケーション プールの詳細設定ダイアログを開き、[開始モード] を [AlwaysRunning] に変更します。

image

3. Web サイトのプリロード機能の有効化

 

プリロードを有効化したい Web サイトの詳細設定ダイアログで [有効化されたプリロード] を True に設定します。

image

これらの設定を変更すると、"C:\Windows\System32\inetsrv\config\applicationHost.config" にそれぞれの設定が追加されます(直接 applicationHost.config を編集しても可)。

 <applicationPools>
    <add name="DefaultAppPool" managedRuntimeVersion="v4.0"
         startMode="AlwaysRunning"  />
</applicationPools>

   ...

<sites>
    <site name="Default Web Site" id="1">
        <application path="/" preloadEnabled="true" >
        </application>
    </site>
</sites>

● Windows Azure クラウドサービスで IIS/ASP.NET オートスタートを使う

続いて、この ASP.NET アプリケーションのオートスタートの設定を Windows Azure クラウド サービスを使った Web アプリケーションで有効にする方法をご紹介します。

クラウド サービスでも Web ロールにリモートデスクトップ (RDP) 接続して、上記と同じ手順で設定は可能です。しかしながら、スケールアップなどの際に、増やしたインスタンス一つ一つに RDP 接続して設定を行うのは現実的ではありません。オートスケールなどでインスタンスが自動で増減する場合はなおさらです。このような場合に、Windows Azure クラウドサービスでは、スタートアップタスクと、ロールの初期化時のイベントハンドラを利用することで、上記のオートスタートの設定を行うことができます。

1. スタートアップタスクで Application Initialization モジュールを有効化する

まず、ASP.NET Web アプリケーションのプロジェクトに Startup.cmd ファイルを追加して、プロパティで [出力ディレクトリにコピー] を [常にコピーする] に設定します。

imageimage

Startup.cmd ファイルには、下記のとおり pkgmgr.exe を使って IIS の Application Initialization を有効化するコマンドを記述します。

 pkgmgr.exe /iu:IIS-ApplicationInit

そして、Windows Azure クラウドサービス プロジェクトにある ServiceDefinition.csdef ファイルを開いて、下記の記述(太字部分)を追加します。

 <ServiceDefinition ...>
  <WebRole name="WebAppPreload" vmsize="Small">

     <Runtime executionContext="elevated"></Runtime> 

     <Startup> <Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple" /> </Startup> 



    ...

  </WebRole>
</ServiceDefinition>

Runtime 要素は、管理者モードで後述の RoleEntlyPoint のハンドラを実行させるための設定で、Startup 要素は、クラウドサービス開始時に実行するスタートアップタスクのコマンドファイルの指定となります。

2. アプリケーション プール開始モードと Web サイトのプリロード機能の有効化

続いて、applicationHost.config へ行うアプリケーションプールの開始モードと Web サイトのプリロードの有効化ですが、下記のようなクラスを Web アプリケーションプロジェクトに追加し、Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint クラスの Run メソッドをオーバーライドして、その中でプログラムコードを通して設定します。

 using Microsoft.Web.Administration;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WebApplication1
{
    public class WebRole : RoleEntryPoint
    {
        public override void Run()
        {
            using (var serverManager = new ServerManager())
            {
                var mainSite = serverManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_Web"];
                var mainApplication = mainSite.Applications["/"];
                mainApplication["preloadEnabled"] = true;

                var mainApplicationPool = serverManager.ApplicationPools[mainApplication.ApplicationPoolName];
                mainApplicationPool["startMode"] = "AlwaysRunning";

                serverManager.CommitChanges();
            }

            base.Run();
        }

        public override bool OnStart()
        {
            return base.OnStart();
        }
    }
}

なお、Microsoft.Web.Administration.ServerManager を使うには、NuGet パッケージマネージャから Microsoft.Web.Administration パッケージ をプロジェクトへ追加します。

image

以上の設定で問題なければ、Windows Azure クラウドサービスでも ASP.NET Web アプリケーションのオートスタートを使用することができます。

● オートスタート有無での初回リクエスト応答時間比較

Windows Azure クラウドサービスを使って、Application_Start メソッドに 2 秒ほどウェイトを入れた ASP.NET Web アプリケーションのオートスタート無効の状態と有効後の状態の初回アクセスでの応答時間を比較してみました。

※ オートスタートなし (リクエスト応答時間: 7 秒)

image

※ オートスタートあり (リクエスト応答時間: 0.141 秒)

image

オートスタートなしの場合は、初回アクセスでワーカープロセスが起動し Application_Start メソッドの初期化処理が行われますので、この例ではページの表示に 7 秒程かかっています。一方で、オートスタートを有効にした場合では、アプリケーション配置後にすぐに初期化処理が始まりますので、この初期化が終わった後に初回アクセスがあった場合には、すぐにページが表示されることになります。上記の例では、およそ 0.141 秒でページのリクエストが完了しています。

この設定をおこなっておくだけで、初回リクエスト時(配置時およびアプリケーションプールのリサイクル後など)の応答速度が改善されますので、ぜひ試してみてください。

※参考情報※

IIS 8.0 Application Initialization module in a Windows Azure Web Role
https://fabriccontroller.net/blog/posts/iis-8-0-application-initialization-module-in-a-windows-azure-web-role/

ASP.NET のパフォーマンスの概要
https://msdn.microsoft.com/ja-jp/library/cc668225(v=vs.100).aspx