IISのオートスタート機能を使ってASP.NET Webアプリケーションの初回実行を行おう

おはようございます。こんにちは。こんばんは。
[【gloops Advent Calendar 2016】](http://qiita.com/advent-calendar/2016/gloops)の12月13日を担当する藤田です。
新卒で「[株式会社gloops](http://gloops.com/)」に入社して来年の4月で3年になるエンジニアです。月日が経つのは早い...！
そんな感じでよろしくお願いします。

# :white_check_mark: はじめに
ASP.NET Webアプリケーションの初回実行は、様々な初期化処理が走ったりするので、処理が重くなります。
その初回実行をする方法の1つとして、Global.asaxのApplication_Startメソッドがあります。

Global.asaxのApplication_Startメソッドは、IISサービスの起動やIISワーカープロセスのリサイクル後、アプリケーションが最初のリクエストを受け取ったタイミングで実行されます。
そのため、初めにページにアクセスしてきた人は、初回実行処理がされて必然的にレスポンスが遅くなります。（ユーザが最初のリクエスト送信者にならないようにするために、サービス提供側が最初のリクエストを送るようにスクリプトを組んだりする方法もあるそうですが、スマートではない気がします。）
それを回避するための機能がIISのオートスタート機能です。
本稿では、そのオートスタート機能の使い方を記載します。

※IISのオートスタート機能は、ASP.NET4及びIIS7.5からの機能なので、結構前からある機能です。
　そのため知っている方も多くいると思いますが、私自身知らなかったので、忘れないよう形として残しておく意味で記載します。

## :pencil2:  オートスタート機能について
IISのオートスタートの発火タイミングは、IISサービスの起動時及び、IISワーカープロセスのリサイクル時です。
Global.asaxのApplication_Startメソッドと違い、サーバに誰かがリクエストを送らずとも発火してくれます。
つまり、オートスタート機能に重い初回のみ実行される処理を寄せることで、最初のリクエスト送信者もその処理分待機することなくレスポンスが返ってくるようになるということです。

## :eyes:  機能を使うためには？
大きく分けて2つ準備の工程があります。
1つ目は、プログラムの実装。
実装と聞くと何やら大変そうなイメージがあるかもですが、実装自体は非常にシンプルです。
2つ目は、IISの設定。
オートスタート機能をオンにする設定と1つ目で実装したプログラムを指定する必要があります。
以上の2つを順を追って説明します。
※IISのアプリケーションプールとサイトは既に作成済みであることを前提に進めます

## :one: プログラムの実装
基本的に、IProcessHostPreloadClientを実装したクラスを実装するだけです。
IProcessHostPreloadClientは、System.Web.Hosting 名前空間にあります。
実装例は下記の通りです。

    using System.Web;
    using System.Web.Hosting;

    namespace TestClassLibrary
    {
        public class ProcessHostPreloadClient : IProcessHostPreloadClient
        {
            public void Preload(string[] parameters)
            {
                HttpRuntime.Cache["Preload"] = "Executed";
            }
        }
    }
Preloadメソッド内に初回実行処理を書きます。
今回は実際に実行できているか確認するために、キャッシュに詰めることをしています。

また、確認用のページも用意しました。
キャッシュがあると「Executed」、ないと「Not Execute」を画面に出すだけのページです。
・Index.aspx

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    </head>

    <body>
        <div>
            Preload:<asp:Literal runat="server" ID="l_cache"/>
        </div>
    </body>
    </html>

・Index.aspx.cs

    using System;
    using System.Web;

    namespace TestProject
    {
        public partial class Index : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var cache = HttpRuntime.Cache["Preload"];
                var message = cache ?? "Not Execute";

                l_cache.Text = message.ToString();
            }
        }
    }

## :two: IISの設定
段階があるので、順に説明します。

1.「Application Initialization」の有効化
「Windowsの機能の有効化または無効化」から下記画像のルートを辿ると「Application Initialization」というものがあります。
デフォルトではチェックがついていないはずなので、チェックを付けてOKをしましょう。
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/dfa1c822-4c7f-0c20-9e8e-67724a4db99e.png)


2.アプリケーションプールの開始モードの変更
IISマネージャーからアプリケーションプールの開始モードを、デフォルトの「OnDemand」から「AlwaysRunning」に変更します。
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/800a0724-5192-eb93-2adc-7684052198e8.png)


3.サイトの設定
1,2までは、[こちら](https://blogs.msdn.microsoft.com/chack/2013/09/25/iis-asp-net-web-2223/)のサイトを参考にさせて頂いて書きましたが、3は方法が違います。（少し長くなります）
2で行ったようなIISの設定は、
C:\Windows\System32\inetsrv\config\applicationHost.config
に書かれているのですが、
サイトの設定は、このconfigファイルを直接書き加えることをします。（一度デスクトップ等に移してからでないと編集ができないので注意）

サイトを作成すると、applicationHost.configの\<system.applicationHost>→\<sites>タグ内にサイトの設定が書かれます。
![7.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/15a24822-4e07-4921-3416-8f56bbe02beb.png)

この\<site>タグの\<application>に、
・serviceAutoStartEnabled="true"
・serviceAutoStartProvider="TestPreload"
上記2つを追記してあげます。以下のような感じで。
![8.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/80ac7dfc-7eea-19cd-9dde-7a94dc22b3aa.png)
「serviceAutoStartEnabled」は、そのままの意味ですが、オートスタート機能を有効にするかどうかを決める属性です。
「serviceAutoStartProvider」は、次に説明する\<serviceAutoStartProviders>と関連付けるための属性です。
「TestPreload」という名前は任意のもので大丈夫です。

次に、初回実行時に呼ぶクラスを定めます。
方法は、\<system.applicationHost>タグ内に\<serviceAutoStartProviders>を下記画像のように設定すればOKです。
![9.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/56955095-27b0-5cc2-bca0-1bf1cc9b888e.png)
nameには、先ほどserviceAutoStartProviderで設定した名前を入れます。
typeには、オートスタートで実行させたいクラス名と名前空間を入れてあげます（type="[クラス名], [名前空間]"）

全体像として以下のような感じになります。参考までに。
![10.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/519a6186-c3f0-e8f4-989b-745574f366c7.png)

以上でオートスタートの準備が整いました。

## :sunglasses:  実行してみる
ちゃんとオートスタートが機能しているのか確認してみます。
F5ポチー・・・
![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/51657/37a55fe9-5683-260a-fbac-263d7ac608d7.png)
お！キャッシュに値が入っていたのでちゃんと機能しているようですね！

# :end: おわりに
アプリケーションサーバのウォームアップを行う機能として非常に便利であると思いました。
今後もこういった知識を深めていって、ストレスフリーなサービスを提供していきたいと思っています！