Heroku での Java セッション処理
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年07月15日(金)
Table of Contents
HTTP はステートレスなプロトコルですが、ほとんどのアプリケーションでは、ログイン状態やショッピングカートの内容のような特定の情報を、リクエスト全体にわたって保持する必要があります。このような状態は通常、セッションに保存されます。
セッションは、クライアント側で暗号化された HTTP Cookie に保存するか、サーバー側でさまざまな永続化メカニズムを使用して保存することができます。どちらのアプローチにも長所と短所がありますが、この記事では、Heroku 上の Java アプリケーションでサーバー側セッションを確実に処理する方法について説明します。この記事のすべての例では、ストレージメカニズムとして Redis を使用します。
Redis を使用してセッションを保存する理由
dyno のステートレスな性質と、水平方向に dyno をスケーリングする必要性に照らして、Heroku では、ファイルベースのセッションストレージおよびインメモリストレージは推奨されていません。ファイルストレージとインメモリストレージのどちらでも、セッションデータは再起動時に失われ、dyno 間で共有できません。さらに、セッションを dyno にローカル保存した場合、ユーザーからの次のリクエストが別の dyno に届き、そこにはセッション情報が存在しないという状況に陥る可能性があります。
Redis インスタンスは、dyno の再起動をまたいでデータを永続化し、複数の dyno 間で共有できるため、セッションを保存するための優れたソリューションです。次のように実行して、Redis インスタンスをアプリに追加できます。
$ heroku addons:create heroku-redis
これにより、アプリで REDIS_URL
の環境設定が行われ、この記事で説明する手順で使用する準備が整います。または、Heroku のサードパーティ Redis アドオンのいずれかを使用することもできます。
Tomcat Webapp Runner を使用したセッションの保存
Heroku 推奨のサーブレットコンテナの Tomcat Webapp Runner には、Redis または Memcached を使用したセッションストレージのサポートが組み込まれています。これを Heroku Data for Redis アドオンと共に使用するには、--session-store redis
オプションを次のように Procfile
に追加することによって Webapp Runner JAR ファイルに渡します。
web: java -jar target/dependency/webapp-runner.jar --session-store redis target/myapp.war
あるいは、heroku war:deploy
または mvn heroku:deploy-war
コマンドを使用している (そのため Procfile
が存在しない) 場合は、次のように実行して環境設定としてこのオプションを設定できます。
$ heroku config:set WEBAPP_RUNNER_OPTS="--session-store redis"
Webapp Runner は、アドオンによって提供された REDIS_URL
環境変数を検出し、それを使用してアプリケーションの HTTP セッションの保存を開始します。
Redisson を使用したセッションの保存
Webapp Runner を使用していない場合、Redis 用の高性能 Java クライアントとして人気が高い Redisson などのライブラリが必要です。これは、セッションストレージなどのさまざまな目的に使用できます。
Redisson では、Tomcat および Spring 用のアダプターを提供しています。その他のサーバーやフレームワークの場合は、Redisson API を直接使用する必要があります。
いずれの場合も、次のように、Java コードで org.redisson.config.Config
オブジェクトを作成する必要があります。
String redisUriString = System.getenv("REDIS_URL");
URI redisUri = URI.create(redisUriString);
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(redisUriString)
.setConnectionPoolSize(10)
.setConnectionMinimumIdleSize(10)
.setTimeout(5000);
if (redisUri.getUserInfo() != null) {
serverConfig.setPassword(redisUri.getUserInfo().substring(redisUri.getUserInfo().indexOf(":")+1));
}
次に、Config
オブジェクトを使用して新しい RedissonClient
インスタンスを作成できます。
RedissonClient redisson = Redisson.create(config);
Spring または Spring Boot を使用している場合は、Redisson のドキュメントで説明されているように、@EnableRedissonHttpSession
アノテーションも必要です。
クライアントでオブジェクトを保存する方法は、フレームワークまたはサーバーの動作方式によって異なります。多数の例と一般的なパターンが Redisson のドキュメントで紹介されています。
その他のオプション
Redis と Memcached の両方でセッションストアを構築するためのクライアントとライブラリは、ほかにも多数存在します。これらには、次のものが含まれます。
- Jedis: Java Redis クライアント
- XMemcached: Java Memcached クライアント
Memcachier のアドオンプロバイダー向けドキュメントでも Memcached への接続例を確認できます。