「セッションステートパターン」をまとめて 3 つ紹介します。
HTTP というプロトコルはステートレスです。TCP ポートとの接続継続が保証される仕組みと異なり、クライアントとサーバーの間には持続的なコンテキストがありません。この特性のおかげで、サーバーのキャパシティを超えた HTML を配信できます。しかし、手続き的な操作が必要なアプリケーションとこの HTTP の特性は、あまり相性の良いものではありません。状態を保持するセッションを、アプリケーションの工夫で設ける必要があります。
Client Session State は、Web ブラウザ側の Cookie など、クライアント側に状態を保持するパターンです。Cookie のほか、クエリパラメータや HTML の hidden タグ、(PoEAA では紹介されていませんが現在では) JavaScript の変数や、その永続化先としてのローカルスロレージといったものに、コンテキストを持続させるための情報を保持します。
Client Session State の欠点は、状態変数が増えたときの通信量です。とくに Cookie は、毎回使うとは限らない情報を送ることになります。また、その 1 エントリの容量はたった 4KB しかありません。クエリパラメータや hidden タグは、連続するリクエストの途中でバトンリレーが途切れてしまうリスクがあります。すべての Client Session State に共通する問題は、虚偽のデータを捏造する余地があることです。
Server Session State は、状態変数の実体をサーバー側に持たせるパターンです。クライアントが持つ変数は、サーバーが持っているデータを特定するための ID だけになります。多くの Web アプリケーションフレームワークで、Server Session State の機能がサポートされています。
Server Session State があるからといって、Web アプリケーションがデスクトップアプリケーションのように、何でもできるようになるわけではありません。サーバーは全ユーザーの状態を一手に抱えることになります。あまりに大きなデータをセッションに入れると、サーバーのキャパシティを超えるおそれがあります。保存したはいいけれど、クライアントが ID を紛失したまま放置されたデータが、ディスクを圧迫してシステムが機能しなくなる問題が考えられます。
Server Session State の中でも、データを共用データベースに置くのが Database Session State パターンです。
HTTP でコンテンツを配信するサーバーのメリットは、ロードバランシングが簡単だということです。機能ごとに異なる物理サーバーに割り振ったり、同じ機能を持つ複数のサーバーにランダムにリクエストを割り振っても、クライアント側にサーバーが 1 台だけのときと同じように見せることができます。このようなスケーリングを意識した場合、各サーバーのメモリやローカルディスクにセッション情報を持たせると、接続の割り振りによってクライアントの状態がちぐはぐになってしまいます。
スケーリングを意識した Web アプリケーションは、セッションの保存先として、アプリケーションサーバーとは異なるデータベースを選択するのが一般的です。セッション情報にとって重要なのはユニーク ID だけなので、現在では Redis のような KVS に、データをシリアライズして格納する方式がよく選択されます。とはいえ、負荷が問題にならないうちは、RDB のテーブルを保存先にしても、十分に役目を果たしてくれるでしょう。
Server Session State を選択する場合は、スケーリングを見越して、ストレージを抽象化して、戦略をプラガブルにしておくのが適当です。逆に、全てを Client Session State とする Web API という選択肢も、現在では十分に考えられます。よほど重要な情報でないかぎりは、シングルページアプリケーションの JavaScript の変数で、十分に状態を管理できるからです。認証トークンの JWT 以外の情報は、必要なときだけ送るようブラウザ内アプリケーションを作ることができると、もっとも効率的で、HTTP のステートレスさとも相性の良いものにできる可能性があります。