ハードウェアの構成
ロードバランサー1台
Webサーバー3台
DBサーバー1台
ソフトウェアの構成
Webサーバー
Windows Server 2008 R2
IIS7.5
ASP.NET MVC 4
IISではひとつのWebサイトの下に複数のASP.NET MVCアプリケーションを配置。
DBサーバー
Windows Server 2008 R2
Microsoft SQLServer 2008
パターン1 - それぞれのWebサーバー内でSessionを管理
ロードバランサーが「セッション維持機能」を持っている事が前提。
Session管理は State Service を使う。
State Service を使う為のweb.configの設定
<sessionstate mode="StateServer"> stateConnectionString="tcpip=127.0.0.1:42424"各Webサーバーで「ASP.NET State Service」が自動起動する様に設定しておく事。
stateNetworkTimeout="10" />
パターン1で発生した問題
ロードバランサーのセッション維持機能が上手く動いていない!
そのため時々Webサーバーが切り替わってログイン画面が表示されてしまう。
ロードバランサーのベンダーに調査してもらっても「設定に特に問題は見つかりません。アプリ側の問題では?」との事で、解決せず。
教訓:しょぼいロードバランサーは使わない!
今回のプロジェクトではロードバランサーは自分達の管理下にはないので、パターン1はあきらめる。
パターン2 - SQLServerでSessionを管理
ロードバランサーのセッション維持機能に頼らずにSession情報をDBに格納してWebサーバー間で共有する事にする。これならWebサーバーが任意のタイミングで切り替わっても大丈夫。
1. SQLサーバーにSession情報を保存するためのデータベースを作成する。
aspnet_regsql.exe -S server -U username -P password -ssadd -sstype p
※tempdbに保存するのではなく永続化するために -sstype pオプションが必要。
このコマンド一発でデータベースの作成、テーブルの作成、期限切れのSession情報を削除するためのJobの登録まで行なってくれる。
aspnet_regsql.exeのヘルプはこちら
2. MachineKeyの設定を共通化する。
全てのWebサーバーでMachineKeyを共通化しておかないと、認証クッキーやその他さまざまなデータの暗号化・復号化の処理がWebサーバーが切り替わった時に上手く行かなくなる。
IIS7.5の管理画面で該当のアプリケーションを選択すると、「MachineKey」という項目があるのでそれを開く。
画面右側の「Generate Keys」をクリックして「Apply」するとweb.configファイルのsystem.webセクションに下の様な設定が追加される。
<machineKey decryptionKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" validationKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
あとはこの部分をコピーして他の2台のWebサーバーのweb.configにペーストすればOK。
参考URL:How To: ASP.NET 2.0 で MachineKey を構成する方法
3. IIS Metabase上のSite IDを共通化する。
これをしておかないと、Webサーバーが切り替わった時にSQLServer側で別アプリケーションとして認識されてしまって、Session情報の共有が出来なくなってしまう。今回はこれでハマった。。。
対策としてはSQLServerのストアドプロシージャを修正するという方法もあるみたいだけど、IIS7.5以降なら下の方法で簡単にIDを共通化出来るみたい。
IIS上で何度かWebサイトを作成したり削除したりしているとIdの値が変わってしまうので、該当のWebサイトを選択した上で「Advanced Settings」を開いてIDの欄に他のサイトと重複しない値を入力する。
他の2台のWebサーバーでも該当のサイトが同じIDを持つ様に入力する。
この設定を行った後は、IISを再起動する必要があるので注意。
おまけ:Forms認証を使う場合の注意点
- 一つのWebサイトの下に複数のアプリケーションを配置する場合は、アプリケーション毎に認証クッキーの名前を変える事。
- 認証クッキーのパスは「/」から変更しない方が良い。
(ブラウザはクッキーのパスについては大文字小文字を区別するが、サーバーはURLの大文字小文字を区別しない為。)
.