daisuzz.log

Spring Session Data Redis (2.4.1) のコードを読んでみる

Spring Session Data Redisのソースコードを読んだので備忘録としてまとめていきます。 ソースコードは以下を読みました。

github.com

Spring Session Data Redisのパッケージ構成

f:id:dais39:20201227175736p:plain

  • Spring Session Data Redisのクラスは全部で13ファイル
  • RedisSessionRepositoryやRedisIndexedSessionRepositoryなどSessionRepositoryをRedis用に拡張したクラスや、RedisSessionExpirationPolicyというRedis上の有効期限を過ぎたセッションを削除するための処理が定義されたクラスなどが定義されている
  • configパッケージ配下には、Spring SessionでRedisを使うためのJavaConfig、設定用のアノテーション、Redisの設定を変更するためのクラスが定義されている

各クラスの概要

SpringSessionRedisOperations

  • Redis用のSessionRepository実装クラスが利用するRedisOperationsをInjectするためのアノテーション
  • コード例
   @SpringSessionRedisOperations
    private RedisOperations<Object, Object> redis;

SpringSessionRedisConnectionFactory

  • RedisIndexedSessionRepositoryにInjectされるRedisConnectionFactoryのためのQualifierアノテーション

EnableRedisHttpSession

  • このアノテーションをJavaConfigに付与すると、@ImportによってRedisHttpSessionConfigurationクラスを読み込む
  • アノテーションに値を設定することで以下の設定を変更できる
    • maxInactiveIntervalInSeconds
    • redisNamespace
      • Redisに格納するキーのprefix
      • デフォルトはspring:session
      • 同じRedisインスタンスに複数のアプリケーションのセッションを保存したいときなどには、これを使うことでセッション情報を別々に識別することができる
    • flushMode
      • セッション情報をRedisにflushするタイミング
      • デフォルトはSessionRepository.save(Session)が呼ばれたタイミング
        • これはWeb環境では、レスポンスがコミットされる直前
    • cleanupCron
      • 期限切れのセッションをcleanupするジョブのCRON設定
      • デフォルトは毎分実行
    • saveMode
      • Redisに書き込むセッション情報
      • デフォルトはセッション情報の変更分のみをRedisに書き込む

RedisHttpSessionConfiguration

  • SessionRepositoryFilterがspringSessionRepositoryFilterというBeanIdでBean定義される
  • RedisHttpSessionConfigurationを使うためには、RedisConnectionFactoryを1つBean定義する必要がある

EnableRedisWebSession

  • このアノテーションを付与すると、@ImportによってRedisWebSessionConfigurationが読み込まれる

RedisWebSessionConfiguration

  • RedisWebSessionConfigurationでは、WebSessionManagerをwebSesssionManagerというBeanIdでBean定義する
  • RedisWebSessionConfigurationを使うためには、ReactiveRedisConnectionFactoryを1つBean定義する必要がある

ConfigureRedisAction

  • Redisの挙動を設定するためのインターフェース
  • このインターフェースではNO_OPという処理が何も書かれていないラムダが定義されている
    • AWSやAzureなどのクラウドサービスで提供されているRedisや、より安全に構築されたRedisなどでCONFIGコマンドが禁止されている場合などに利用

ConfigureNotifyKeyspaceEventsAction

  • ConfigureRedisActionの実装クラス
  • Redisの一般的な(Generic)コマンドのためのKeyspace eventと期限切れイベント(Expired event)の通知を有効にする設定をおこなうクラス
  • Redisのnotify-key-space-eventsの値を、すでに設定された値に応じて上書きする
    • Eが設定されていなければ、Eを設定
    • Aとgの両方が設定されていなければ、gを設定
    • Aとxの両方が設定されていなければ、xを設定
  • Redisのnotify-key-space-eventsの設定値は以下を参照
    • Redis Keyspace Notifications – Redis
    • E
      • __keyspace@<db>__から始まるKeyspace eventを通知する
    • g
      • Redisの型関係なく使えるコマンドの実行イベントを通知する
    • x
      • 期限切れになった際に発火されるExpired eventを通知する
  • Spring BootでSpring Session Data Redisを利用する場合は、デフォルトでこの実装クラスが有効になっている

RedisSessionRepository

  • SessionRepositoryの実装クラス
    • SessionRepository
      • Sessionを利用するための最も基本のAPIを提供するインターフェース
      • Sessionインスタンスの作成, 取得, 永続化をおこなう
  • RedisOperationsを使ってセッション情報をRedisに格納する
  • セッションのイベントの通知はサポートしていない
  • 内部クラスとしてRedisSessionRepository.RedisSessionクラスが定義されている

RedisIndexedSessionRepository

  • RedisOperationsを使ったFindByIndexNameSessionRepositoryの実装クラス
    • FindByINdexNameSessionRepository
      • SessionRepositoryを機能拡張したインターフェース
      • 引数で与えたインデックス名やインデックスの値に紐づく全てのセッションを取得する機能を提供
      • 一般的なユースケースとしては、特定のユーザの全てのセッションを検索するケースがある
  • SessionMessageListenerを介することでSessionDeletedEventとSessionExpiredEventをサポートしている
  • configureSessionChannelsメソッドでイベントを検知するためのチャネル(イベント名)やセッションキーのprefixを設定している
    • <namespace名>event:<database名>:created:というイベント名のものをSessionCreatedEventとして扱う
    • __keyevent@<database名>__:delというイベント名のものをSessionDeletedEventとして扱う
    • __keyevent@<database名>__:expiredというイベント名のものをSessionExpiredEventとして扱う
  • 内部クラスとしてRedisSessionRepository.RedisSessionクラスが定義されている

ReactiveRedisSessionRepository

  • ReactiveRedisOperationsを使った、ReactiveSessionRepositoryの実装クラス
  • 内部クラスとしてRedisSessionRepository.RedisSessionクラスが定義されている

RedisSessionExpirationPolicy

  • 有効期限を過ぎたRedisIndexedSessionRepository.RedisSessionインスタンスを削除するためのStrategyクラス
  • Redisはexpired session eventを発火するタイミングを保証していない
  • expired session eventをすぐに処理することを保証するために、Spring Sessionではある時間と、その時間周辺(正確には、実行した時間の秒数を無視した時間)に期限切れを迎える全てセッションを紐づけている
  • cleanExpiredSessionsメソッドが呼ばれると、期限切れになったものが削除されているか確認するために、紐づいたセッション情報にアクセスする
    1. 現在時間から秒数を無視した時間に紐づくセッション情報を取得
    2. expirations keyを削除
    3. 1で取得したセッション情報1つ1つのキーがRedis上に存在するか確認する
  • デフォルトではcron taskとして毎分cleanExpiredSessionが呼ばれる実装になっている

RedisSessionMapper

  • Functionインターフェースの実装クラス
  • Mapで表現されたRedis HashをMapSessionに変換する

This entry is released under version 2.0 of the Apache License.