ASP.NET Univarsal Providersのセッションプロバイダって、セッションの破棄もしてくれるの?という話題から。
結論から言うと、「期限切れのセッションは削除してくれます。但しパフォーマンスに問題がありそうなやり方で。」となります。
@kazuk さんにさらっと見てもらえたので先に結論がわかりました。ありがとうございます。
さて実際にその様を見てみましょうか。
実装を見るためにILSpyでSystem.Web.Providers.dllを見てみようと思います。
とまぁInitializeRequest内で(リクエストが来た時点で)無条件にDBから期限切れの一覧を取得してバッサリ削除するという残念仕様な様子。
実行してるクエリはこんな感じ。あとSessionsテーブル見るとインデックスないのでイヤンということらしいです。
つまるところ、セッションが増えればリクエストのたびにこの処理走るのでパフォーマンスはお察しください、という。
とほほ。まぁ確実にゴミセッションは削除されますが…
まぁ一応動作見てみましょう。
サンプルなので適当にコントローラー内で、セッション上のデータが無ければセッションに日付保存します。
Viewでさくっとセッション関連の情報ほ表示。
ではテストしてみます。実行して接続するとセッションオブジェクトが作成されてSessionsテーブルに保存されます。
※既定でセッションタイムアウトは20分ですが、待ってられないので3分にしてます。
で、しばらく放置して期限切れになった後別ブラウザで接続してみます。
ちゃんと別セッションですね。ではSessionsテーブル見てみましょう。
ハイ消えた!古い期限切れセッション消えた!今消えた!
ということで新しい接続があった際に期限切れをバッサリ削除するという想定通りな動きになりました。
ちなみにSQL Expressで動かしましたが、SQL Agentなどは動いていませんので接続が無ければずっとセッションは残りっぱなしです。
まぁMembershipProviderとかはそのまま便利に使えますし、SessionProviderも小規模であればちゃんとセッション削除できるしSQL Azureでも使えるし、まぁいいんじゃないでしょうか。
パフォーマンスはアレですが。(少なくとも今出回ってるSQL Azureで使う場合(ASP.NET標準のSQL Server使った手法)よりは簡単に実装できるし便利は便利です)
ただ、セッションIDの生成ルールはASP.NET標準のセッションプロバイダのルールに則るので HttpRuntime.AppDomainAppId (例:/LM/W2SVC/1/ROOT/ )がセッションIDの後ろに付与されます。
つまりどういうことかというと、アプリケーションIDがランダムでバラバラになる複数インスタンスのWindows Azure上だとSQL Azure使ってもセッション共有できないんですね。
ということでいろいろ話聞くとSQL Server Compact等ストアド使えないので SessionIDManager を継承してCraeteSessionIDメソッドを実装したクラス作ってsessionState要素のsessionIDManagerType属性に指定するのがいい様子。
もうちょっとややこしい話な様子…あとで再考。
あとはMachineKeyの指定も要りますよね?
というわけでこんな感じでいた。パフォーマンスあたりは次回簡単にまとめてみようと思います。
ピンバック: 蒼の王座 » ASP.NET Universal ProviderをSQL的側面から見てみた