LoginSignup
1
2

More than 3 years have passed since last update.

Rails 4.2.x から 5.0.x にアップグレードする際にカナリアリリースすると session が取得できなくなる不具合を回避する

Last updated at Posted at 2020-08-27

はじめに

  • カナリアリリースとは複数サーバのうちの一部にだけ新しいバージョンのアプリケーションをリリースするデプロイ手法である
  • Rails 4.2.x から 5.0.x にアップグレードする際にカナリアリリースをする、つまり Rails 4.2.x と 5.0.x のアプリケーションが混在した環境を作ると session が取得できなくなる不具合が発生するのでこれを回避したい

この時世に Rails 5.0.x へのアップグレード(しかもカナリアリリースを挟んで)をする方がいらっしゃるのかは不明ですが、どなたかの役に立てば幸いです :pray:

Ruby や Rails をある程度触ってる方向けの内容なので、Rails における session や rack などの基礎的な説明は省きます。

解決方法

  • rack gem のバージョンを 2.0.7 に固定する

原因を一言で

Rails 4.2.x -> 5.0.x のアップグレードに引きずられて rack gem が 2.0.8 以上にアップデートされるのが原因。(rack の 2.0.7 -> 2.0.8 で session_id の生成ロジックに破壊的な変更がある)

See. https://github.com/rack/rack/blob/master/CHANGELOG.md#208---2019-12-08

説明

rack の 2.0.7...2.0.8 の差分lib/rack/session/abstract/id.rb, lib/rack/session/memcache.rb 辺りを見るととても分かりやすい。

  • rack 2.0.7 まではブラウザの cookie に保存されてる _session_idRails 側で命名) の値をそのままセッションストア(Redis や Memcached など)のキーにしていた
  • rack 2.0.8 からは _session_idDigest::SHA256.hexdigest した値をキーにするようになった(コードはこの辺りpublic_id_session_id に等しい)
  • 各セッションストアの gem で #get_session_with_fallback という fallback 用のメソッドを用意している(redis-rack の場合, Memcache の場合)ので、新しいバージョンの rack から古いバージョンの rack で生成したセッションデータを取得することはできるが、逆はできない。つまり、後方互換性はあるが、前方互換性がない

上記より、新しいバージョンの rack gem を全サーバに一度にデプロイすれば問題ないが、各サーバで 2.0.7 以下と 2.0.8 以上の rack gem が混在する環境(カナリアリリース環境)だと session が取得できなくなる。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2