とあるXML WEBサービスを.NETで開発したのですが、
たまに(負荷が集中すると)おかしな状況になります。
例えば、シングルトンで持っている static オブジェクトの
フィールドがふっとんでしまいます。
スコープ内のオブジェクト変数がnullになったり、
挙動が不審・・・
さて、ここからはASP.NETのセッションステートプロセスモデルのお話です。
ASP.NETのセッションプロセスモデルは、以下の3タイプがあります。
・InProc(インプロセス)
・StateServer(ステートサーバー)
・SQLServer(SQL Server)
よく言われている話で、前者ほど高速だが信頼性が低いとのことです。
InProcの場合、IIS再起動やサーバ再起動でセッションは失われますとの
説明もよく目にします。
「あぁ再起動する時は別にセッション消えても仕方ないよ。
高速なInProcを使おう」
となっちゃうわけです。
でも、ちょっと待って下さい。
以下のページにはこう書いてあります。
************************************************
(.NETエンタープライズWebアプリケーション開発技術大全
Sessionオブジェクトより)
InProcモードとStateServerモードの違い
・Webサーバの障害時にSessionデータが消失するという点では同じである。
・しかしInProcモードでは、アプリケーションリスタートやプロセスリサイクリング
が発生した際にもSessionデータが消失する。
************************************************
プロセスリサイクリング?
簡単に調べてみました。
************************************************
(クライアントステート管理、3つの手法より)
WindowsServer2003上のIIS6では、29時間ごとにワーカープロセスが
自動リサイクルされる
************************************************
おいおい、、、IIS再起動とかサーバ再起動とか以前に、
「必ず」セッション破棄されちゃうじゃん・・・
そして、以下もプロセスリサイクリングの一環と読み取れました。
************************************************
(IIS 6.0の機能の詳細より)
信頼性の向上を目的としたコンポーネントである
「WWW Service Administration and Monitoring Component」
は、ワーカー・プロセスの異常動作を検出し、
修復するための仕組みである。
このコンポーネントはワーカー・プロセスの状態を逐一監視し、
異常を検出すると、ただちにワーカー・プロセスを再起動するなど、
正常化に向けたアクションを実行する。
************************************************
以下がその既定値です。
・メモリ
仮想メモリを500Mbytes以上消費した
・CPU
5分間CPU使用率が100%になった
・ping
30秒おきに実行されるpingにプロセスが反応しなかった
・プロセス・エラー
5分間に5回以上のエラーが発生した
同時負荷テストなんかだと、CPUやpingは普通に条件を満たしそうです。
そうなんです。冒頭の私のトラブルは、これが原因ではないかと
にらんでいます。(まだ、推測の域ですが)
一応、上記「IIS 6.0の機能の詳細」にあるようにIIS側で
設定を変更できるようです。
でも、結局サーバがやばい状況になってるのは確かなんで、
こっちのシステムの見直しが必要なんでしょうね・・・
そう、セッションに巨大なデータを格納しちゃ駄目なんです。やっぱり。
どうもこの結論だけが先行してて、理屈が抜きになっている気がします。
「こんな理由で駄目なんだよ」って納得しないと、プログラマって
なかなか言うこと聞かないんですよね・・・
ところで、試しにStateServerを利用する作り改修して
InProcモードと比較してみました。
負荷テスト結果としては、巷で言われるほどパフォーマンスに違いはなく、
むしろ高負荷ではStateServer(別サーバ)の方が高速。
サーバが一台じゃなければ、StateServerの方がイイかも。
StateServerへの設定は、こちら↓のページによくまとまっています。
[ASP.NET の Session State Server を使う]
なお、StateServerを利用する場合は、以下の点に注意が必要です。
************************************************
(.NETエンタープライズWebアプリケーション開発技術大全
Sessionオブジェクトより)
・Session_OnEndイベントは使えない
Session_OnEndイベントは、使わないようにしよう。
なぜならば、このイベントはインプロセスモードで作られた
セッションの場合に限り呼び出され、アウトプロセスモードで
作られたセッションでは、セッションが破棄されても発生しない
・格納するオブジェクトは、シリアライズ可能である必要がある
カスタムクラスを作っており、それをセッション状態に保存したいのであれば、
対象とするクラスに[Serializable]メタデータ属性を付加するか、
ISerializableインタフェースを実装しなければならない
([Serializable]はC#のメタデータ属性で、
************************************************
とりあえず、本件でつくづく感じたことは、自分の未熟なスキル。
まだまだお客様の期待に応える品質でシステム提供できていないようです。
忙しくなると、自分を高める努力を怠りがちです。反省せねば・・・
↓のページの解説を全て身につけると、スーパープログラマに
一歩近づく感じ。
[.NET アプリケーションのパフォーマンスとスケーラビリティの向上]
以前、パフォーマンスに関する章はかなり熟読したけど、さすがに全ては
目を通せていません。
通勤時間にフルブラウザを利用して、地道に読むかな・・・
あ、情報処理試験があるんだった(^^;)
■まとめ
自分なりの結論です。というか今後のポリシーです。
(今は無理なんです・・・)
・セッションのInProcは禁止。開発時はローカルマシンでStateServerとする
→シリアライズ不可なオブジェクトを格納している場合に
開発時に気づくことができる
・そもそも、セッションをなるべく使わない
→1メソッド完結型がイイよ・・・
どういう理由で危ないのかを説明できれば、
きっとお客様も納得してくれるでしょう
・ASP.NETで使われる可能性のあるコンポーネント開発は、
[Serializable]属性ON
→今のところ調べた範囲では、デメリットは特に無さそう


webアプリの開発には端末アプリでは考えられない変なことが起こるのですね。
実は私はSingletonを最近知りました。それまでのプログラムでは、メインフォームのクラスがインスタンスを保持していたのですが、それだと他のクラスで参照するときにとても面倒でした。
デザインパターンは結構使われるものなのでしょうか。
ホントですよね。スコープ内の変数の値がふっとんでいるのとか、
自分の中で状況が理解できなくて困ってます(^^;)
>実は私はSingletonを最近知りました。
私もSingletonを実開発で使い出したのは結構最近でした(多分、1,2年前)。
設定情報やらログ出力やらをSingletonで管理すると開発しやすいので、
ついつい使いまくった時期もあります。
多分、オブジェクト指向にうるさい人ならクラス設計が云々って
話になるんだと思いますが・・・
デザインパターンってとっつきにくいですが、結構知らず知らずのうちに
使ってたりします。
開発テクニックとして自分の引き出しが増えることに意味があると思っています。
私は偉そうに語るほど活用してませんけど(^^;)
ありがとう。
ご参考になれば幸いです。
ちなみに、冒頭の問題はスレッドセーフになってない箇所があっただけ・・・
だった記憶があります(汗
とはいえ、この時のセッション関連の調査は最近役立ったりしてるので
無駄ではないと思ってます☆
何となく、昔ながらの仕組みを残しただけな感がありますよね。