当将Rails版本从4.2.x升级到5.0.x时,进行金丝雀发布以避免无法获取会话(session)的故障
首先
-
- カナリアリリースとは複数サーバのうちの一部にだけ新しいバージョンのアプリケーションをリリースするデプロイ手法である
- Rails 4.2.x から 5.0.x にアップグレードする際にカナリアリリースをする、つまり Rails 4.2.x と 5.0.x のアプリケーションが混在した環境を作ると session が取得できなくなる不具合が発生するのでこれを回避したい
目前这个时代是否有人正在进行升级到Rails 5.0.x(甚至插入金丝雀发布)并不确定,但如果能对某人有所帮助那将是幸运的。
这篇文章适合那些对Ruby和Rails有一定了解的人,所以我会跳过对Rails中session和rack等基础知识的解释。
解决方案 (jiě jué àn)
- 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 生成逻辑进行破坏性变更。)
请查看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_id(Rails 側で命名) の値をそのままセッションストア(Redis や Memcached など)のキーにしていた
-
- rack 2.0.8 からは _session_id を Digest::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。