🦔

DynamoDBSessionManagerの仕様と課題

2022/09/25に公開

DynamoDBSessionManager とは何か

AWS 環境(複数台のサーバが存在する環境)で Tomcat のセッションを使用する場合、どのようにそのセッションを維持するかということが課題になります。
例えば EC2 上で Tomcat を動かす場合、Java 処理から session.setAttribute()などでセッション登録を行った場合、サーバ内のメモリとディスクを使用して、Tomcat が発番したセッション ID に紐づける形で保持されます。

この時、Web サーバが複数台存在するとすると、セッション情報はそれぞれの Web サーバが保持しているので、利用者(ユーザ)は同じ人は常に同じサーバに接続しないとセッションが切れてしまいます。

そのため、一般的にサーバ手前の ALB (ApplicationLoadBalancer)で、Cookie を用いて利用者(ユーザ)ごとの接続先サーバを覚えておき、毎回同じサーバにアクセスが行くように制御します。(スティッキーセッションと言います)

常に Web サーバが全台稼働しており増減しないのであれば、これで問題ないのですが、以下のようなケースで利用者(ユーザ)がアクセスする先のサーバが切り替わるために、セッションが参照できなくなってしまう問題が発生します。

  • AutoScalling で構成したサーバ(EC2)がスケールインして台数が減る場合
  • サーバ(EC2)に障害が発生した場合
  • リリース作業時に Blue-Green デプロイなどによりサーバが切り替わる場合

このような状態になることを防ぐために、サーバ(EC2)内に個別に保持していたセッションをどのサーバからでも参照できる領域に退避しておき、サーバ切替が発生した場合に参照できるようにする必要が出てきます。

このセッション情報の退避領域として AWS の DynamoDB を使用するため、 Tomcat で動作するライブラリが、DynamoDBSessionManager です。

DynamoDBSessionManager を用いると、EC2 内にセッションを保存したり更新した場合、そのデータを DynamoDB に自動的に退避してくれるようになり、サーバが切り替わった際に、新しいサーバ内に対象セッション ID のデータが無い場合、DynamoDB を参照してくれて、セッション情報を自動的に復元してくれます。

ライブラリを導入し Tomcat 側の設定を行っておくことで、アプリケーション実装としては意識することなく、セッション情報を DynamoDB に退避できるのがメリットということになります。

DynamoDBSessionManager の仕様上の注意点(タイムラグ問題)

上述の通り、アプリケーション実装として意識することなく実装できるのがメリットではあるのですが、DynamoDBSessionManager には仕組み上の注意点(課題点)があります。

EC2 上で動作するアプリケーションから、セッションの登録や更新を行った場合、すぐに DynamoDB にコピーされるわけではありません。一定時間以上使用されていないデータが、DynamoDB にコピーされるという動きをします。
この一定時間以上というのは DynamoDBSessionManager の設定で制御できますが、デフォルトで 60 秒以上かかり、設定変更しても 1 秒以上は必要となります。
つまり、利用者(ユーザ)がまさに利用中の状態で急に経路が切り替わると、最新のセッションデータにアクセスできるとは限らないということになります。

Tomcat が停止する際に、全セッションデータを DynamoDB に退避するという設定を行うことができますが、これは Tomcat が正常に停止できた場合に限られるため、切替かたやタイミングによっては切替後のサーバから最新のセッション情報を参照できません。(一定時間以上使用されていないデータが退避されるということから、正にちょうど使用している利用者(ユーザ)のデータは DynamoDB 上に保管されていない可能性が高いということになります)

サーバの経路切り替わりが発生した際に、新しい EC2 にアクセスが来た場合、対象のセッション ID が EC2 内に存在しない場合、DynamoDB に対して参照を行い、データが存在する場合そのデータをロード(SwapIn)します。

この時取得したデータは、切替前のサーバのセッションデータよりも古いデータである可能性があるという意味で、再操作すれば問題ないのであればさほど問題になりませんが、ショッピングカートのような使い方であったり、処理対象を特定するようなキー情報をセッションで扱っている場合に、不整合が発生するなどが考えられる場合には問題になってきます。

今後メンテナンスされないと考えられる点

DynamoDBSessionManager のライブラリは GitHub の以下リポジトリで公開されています。

https://github.com/amazon-archives/aws-dynamodb-session-tomcat

しかし、すでにThis repository has been archived by the owner. It is now read-only.の表示となっており、これは、既に更新が行われない状態となっていることを示しています。

更新が行われないということは、新しいバージョンの Java で対応することができなかったり、重要な脆弱性が発見された場合にメンテナンスされない可能性があることを示しています。

結論

Tomcat 側の設定のみで実装できるため、アプリケーション実装負荷が低く、パッケージ利用している場合などその部分を意識せずに AWS 環境で動作させることができるメリットがあった DynamoDBSessionManager ですが、上記のような課題点および今後メンテナンスされないと想定されることから、新規の実装は避けるべきでしょう。

次のような選択肢を検討していくことになるかと思います。

  1. AWS SDK を用いてアプリケーションから直接 DynamoDB に対してセッションデータを更新/参照する構成とする。
  2. ElastiCache 等を用いて、アプリケーションから直接セッションデータを更新/参照する構成とする。
  3. そもそもセッション情報のサーバ間の共有を行わない。(スティッキーセッションのみで運用する)

そもそも基本的には、極力 Web サーバはステートレスにしておく(状態を持たずに単純な通り道としておく)ほうが望ましいと考えると、構築するアプリケーションの仕組みにもよるかと思いますが、1 か 2 の選択肢を考えていくことが現実的かと思います。

パッケージ製品などにおいては、まだまだミドルウェアのセッションに依存するつくりのものが多いと思いますので、構成によっては簡単ではないかもしれませんが、これから新しく構成していくアプリケーションは、状態保持にミドルウェアのセッションを用いる前に、どのようにアプリケーションの「状態」を管理するか、構成を十分検討してから開発を進めていくべきかと思います。

Discussion