Memcached とか Redis にセッション状態を保存する

前回の記事から1年以上も経ってる…今年は頑張ります。

最近仕事でセッション状態を NoSQL DB に突っ込めるか?みたいなことを調べたのでメモ。

セッション状態を任意のデータストアに保存するには

SessionStateStoreProviderBase を継承した自前の CustomSessionStatoeStoreProvider を作成して、 いくつかのメソッドをオーバーライドすれば良いです。 実装量もたいしたことないですね、数百行あればできちゃいます。

MSDN には Access に保存する完全なサンプルもありますので参考までに。

SessionStateStoreProvider の各メソッドの仕様はここ に書いてあります。

で、まあこっちの概要読めば分かるんですが SessionStateStoreProvider って SessionStateModule というクラスから使われること前提の設計なので、単体で見ると何すれば良いか結構分かり難いんですよね。私は最初に仕様を読んだんですがさっぱりでした。なので、先に MSDN のサンプル実装眺めて概要把握するのをオススメしますん。

Memcached にセッション状態を格納する

では、NoSQL にセッション状態を格納していきます。

といっても、基本は MSDN のサンプル通り実装して、データアクセスの部分だけちょっと書き換えるだけなので何も難しいところはないんですけどね。一応自分が書いたの置いておきます。

https://github.com/kendi/MemcachedSessionStateStoreProvider

データアクセスには Enyim.Memcached を使っています。

※使い方

↑のカスタムセッションプロバイダを適当な WebApplication プロジェクトに追加して、EnyimMemcached を参照します。(Nuget から取ってこれます)

そして、構成ファイルに Enyim.Memcached の設定と、カスタムセッション状態プロバイダの指定を行います。 Enyim.Memcached の設定は先方のヘルプを見てもらうとして、カスタムセッション状態プロバイダの指定は↓をそのまま貼り付ければ良いです。あ、既に sessionState 要素が存在する場合は置き換えてくださいね。

<sessionState mode="Custom" customProvider="MemcachedSessionProvider" timeout="30">
    <providers>
        <add name="MemcachedSessionProvider"
                 type="namespace.classname, assemblyname" />
    </providers>
</sessionState>

カスタムセッション状態プロバイダのライブラリ

で私の作ったプロバイダなんですが、遅いです…

後述するライブラリの倍くらい時間かかってるんですよねー。ちゃんと調べてませんが、排他制御がまずいのかな?データの格納も、サンプルに従って無駄に ValueObject 作っちゃってるんで、ここも要改善ですね。時間を作って手を付けたいところです。

今すぐ高機能なプロバイダが欲しいのであれば既存のライブラリ使っちゃう手もあります。数は多くないですが、いくつかあって、

例えば Memcached ならこれ。ただこのライブラリは注意点があって、Memcached への接続には Enyim.Memcached 使ってるんですがバージョンふるいのでホスト名での接続先指定が出来ません。

Redis ならこれがパフォーマンスも良くておすすめです。ググればもうひとつ出てくるんですが、排他制御をサボっててマルチスレッドで上手く動かないのでおすすめしません。修正は容易なので自力で直せる人だけどうぞ。気が向いたらプルリク投げるかも知れません。