読者です 読者をやめる 読者になる 読者になる

プログラマでありたい

おっさんになっても、プログラマでありつづけたい

アプリケーション・サーバのセッションの保存先の話

STRATEGY "ELECTRIC SOUP" FRONT


 Webシステムの方式設計をする際に、わりと悩むのがアプリケーション・サーバのセッション(session)の保存先です。アプリケーションサーバとは、TomcatやJBoss,IISやRuby on Railsなどで利用するUnicornやPassengerなどです。そもそもHTTPの基本仕様がステートレスな為、状態を保持する為にはどこかに状態を保持する必要があります。その解決策がセッションになります。そこでセッションの保存戦略を考える必要があるのですが、アプリケーションサーバやサイトの用途や性格、扱うデータの気密性・重要性によっても変わってきます。
 それ以前にセッションの保存先のことの呼び方の定番が何かすら解らなかったりします。セッション・ストアとかセッション・ストレージとか、はたまたセッション・マネージャーとか。今回は、セッション・ストアで統一します。

主なセッションストアの種類と保存戦略


  • ローカルストア

 一番シンプルなパターンが、アプリケーション・サーバ単体で保存する方法です。IISやTomcatなど、何も考えないとこのパターンになります。メリットとしては、単純なので負荷も少なく考慮するポイントも少ない点です。デメリットとしては、セッションが保存されたサーバ以外にアクセスした場合は一切情報が無い状態になります。システムが複数台のサーバで構成されている場合は、手前のロードバランサ等で必ず同じサーバに寄せる(スティッキーにする)必要があります。最近の潮流としては、ロードバランサでスティッキーを保証するような仕組みは推奨されていません。

  • ローカルストア+同期

 アプリケーション・サーバは、自分のローカルのセッションストアを見に行くという点では同じです。ただし、セッションストア間でセッションデータを同期して、他のサーバに接続した場合でも情報があるようにします。メリットとしては、単純なローカルストアの問題点を解決出来ることです。デメリットとしては、同期のリアルタイム性を保証するのが難しいので、同期前に違うサーバにアクセスされることが発生しうるということと、サーバの台数が増える程に同期対象が幾何学的に増える為、せいぜい数台くらいのサーバでしか実用的には難しいことがあります。また最近ではAWSを始めとするクラウドでは、負荷に応じて動的にサーバを増減することがあります。その際に新たに立ち上がったサーバにどうセッションを同期するかという問題があります。

  • 共用セッションストア

 セッションストアをアプリケーション・サーバから分離して、共用セッションストアとして専用のキャッシュセッション・サーバを用意する方法です。セッションの入れ先としてはアプリケーションサーバもしくはプラグインの実装次第で、MySQLなどのRDBであったりmemcachedやredisなどのKVSなどがあります。セッションのデータ構造上KVS型の実装の方が軽量で人気があるようです。
 メリットとしては、ローカルストア+同期の問題をほぼ解決出来ます。デメリットとしては、キャッシュセッション・サーバのスケールアウトや切り替えが難しい点があります。スケールアウトをすると前述の同期の問題を考える必要がありますし、障害等で切り替えが必要な場合はアプリケーション・サーバ側で切り替える、もしくは名前解決等で切り替える機構が必要になります。
 AWSのElastiCacheは、共用セッションストレージの実装と考えることも出来ます。
2013/08/02 15:15追記 キャッシュサーバという呼び方が不適切なような気がするので、セッション・サーバに変更します。

  • クッキーストア

 上で紹介した3つの方法はサーバ側でセッションを保存する方法です。これに対して、クッキーストアはクライアント側に保持する仕組みです。セキュリティの考え方から以前は否定されていましたが、Rails2.0以降はこの方式がデフォルトになったり、Facebook等で採用されていたりと広がりを見せています。
 メリットとしては、上記3つの問題を考えなくて済むという点です。またクライアント側のリソースを利用できるので、サーバ側の負荷は極小です。デメリットとしては、改ざんと盗聴の危険性が起こりうるという点です。改ざんについては、クライアント側に保存されているのでユーザは容易に変更が出来ます。対策として、クッキー署名や暗号化などがあります。盗聴については、都度データの中身を送るので通信を傍受すれば盗聴可能です。この対策としては、httpsなどの通信の暗号化と値の暗号化などがあります。また昔の携帯電話のブラウザ等は、クッキー自体が使えなかったので、そもそもこの方式がとれませんでした。

どの方法が良いのか?



 結局、どの方法が良いのでしょうか?基本的には、ローカルセッションは、セッション保持が必要なシステムであれば採用できません。ローカルセッション+同期の方法は、実際のところ運用が難しく余り採用したくはありません。しかし、Java系のアプリケーション・サーバはこの方法が主流なようで、他の選択肢が少ないように思えます。
 共用ストア方法は、個人的には好んで使う方法です。ただし、管理するサーバが増える点と、スケールアウトの問題がつきまといます。最後のクッキーストアですが、今のところ最も可能性を感じています。実際のところ、どれくらい使われているのでしょうね?特にエンタープライズでの同行が気になるところです。今のところは、悩みを並べるだけで解はもっていません。少し整理していく予定です。安全に使う為のノウハウ等ためていきたいですね。


See Also:
CAPの定理と分散データベースの話