Slide 1

Slide 1 text

メインAPIのRailsバージョンを4.2→6.0に上げた話 〜バージョンアップは計画的に〜 スペースマーケット 技術部 SREチーム 鈴木 景介

Slide 2

Slide 2 text

2 自己紹介 鈴木 景介 (すずき けいすけ) 経歴: 公務員 → フリーター → 2019年1月ス ペースマーケットにバックエンドエンジニ アとしてジョイン (最近はインフラがメイン) 趣味: 読書、筋トレ、サウナ

Slide 3

Slide 3 text

3 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 4

Slide 4 text

4 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 5

Slide 5 text

5 2018年11月以前のAPI構成 長らくAPI側は単一のアプリケーションで構成されていた

Slide 6

Slide 6 text

6 2021年6月時点のAPI構成 現在ではAPI側は主に3サービスに分割されている

Slide 7

Slide 7 text

7 2021年6月時点のAPI構成 スペースマーケットのサービス分割粒度の考え方については 前回ミートアップの資料(タイトル:「マイクロサービスの取り組 み」)をご参照ください!

Slide 8

Slide 8 text

8 2021年6月時点のAPI構成 現在ではAPI側は主に3サービスに分割されている

Slide 9

Slide 9 text

9 2021年6月時点のAPI構成 現在ではAPI側は主に3サービスに分割されている 今回話すのはここ! Rails6 Rails4

Slide 10

Slide 10 text

10 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 11

Slide 11 text

11 メインAPIのRailsバージョンを4.2 → 6.0に上げました Rails バージョン一覧
 
     4.0 → 4.1 → 4.2 
     ↓
     5.0 → 5.1 → 5.2
     ↓ 
     6.0 → 6.1


Slide 12

Slide 12 text

12 ● Rails 6 に上げるために必要な Syntax的変更(一部) ○ modelのuniqueness に case_sensitive 追加 ○ ActiveRecord::AttributeMethod::Dirtyのメソッド名変更への対応 ■ attribute_changed? → saved_change_to_attribute? ■ attribute_was → attribute_before_last_save ● マルチDB接続方法を変更 ○ octopus -> Rails 6 標準のマルチDB接続へ ● 技術的負債の返済 ○ SQLiteに残っていたデータを MySQLに移行 ○ 古いgemのバージョンアップ メインAPIのRailsバージョンを4.2 →6.0に上げました 主な対応内容

Slide 13

Slide 13 text

13 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 14

Slide 14 text

14 セキュリティリスクへの対応

Slide 15

Slide 15 text

15 セキュリティリスクへの対応 ● Rails のメンテナンスポリシーは、新機能 (New feature)、バグ修正 (bug fixes)、セキュリティ問題 (security issues)、重大なセキュリティ問題 (severe security issue) の4つに分割されている ● 上記の4つのうち、Rails4.2は「セキュリティ問題」と「重大なセキュリティ問 題」のサポートが切れていた ○ Rails自体にセキュリティ問題が発覚しても自力で修正する必要があると いう状態だった😨

Slide 16

Slide 16 text

16 開発効率の向上

Slide 17

Slide 17 text

17 ● Enumerableモジュールに#pluck, #withoutが追加 ● ActiveRecordの#saveにtouchオプションが追加 ○ touch: falseとすることでタイムスタンプを更新しないようにできる ● ActiveRecord::Relation#in_batchesメソッドが追加 開発効率の向上 Rails5から使えるようになった機能、メソッド

Slide 18

Slide 18 text

18 ● 並列テスト ● 複数DB接続 ● DBへのバルクインサートの標準サポート ● ActiveRecord:Relation#pick 開発効率の向上 Rails6から使えるようになった機能、メソッド

Slide 19

Slide 19 text

19 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 20

Slide 20 text

20 基本方針

Slide 21

Slide 21 text

21 基本方針 ● Railsのバージョンは4.2 → 6.0まで上げる ○ 本来なら4.2 → 5.0、5.0 → 5.2、5.2 → 6.0と段階的に上げるのがよ かったのかもしれないが、以下の理由から一気に上げることとした ■ 他APIですでに4系から6系に上げた実績があったため ● Rails 4 → 5 は大変であるが、5 → 6は楽にあげることができ た ■ 同じ工程(修正→テスト→リリース)を3度行うより工数が少なく済み そうなため ● 事前に影響範囲を減らすために断捨離しておく

Slide 22

Slide 22 text

22 ドキュメントと他社事例を読み込み

Slide 23

Slide 23 text

23 ドキュメントと他社事例を読み込み ● 公式ドキュメント ○ Rails アップグレードガイド ○ リリースノート ■ 4.2 → 5.0 ■ 5.0 → 5.1 ■ 5.1 → 5.2 ■ 5.2 → 6.0 ● 他社事例をいくつか参照

Slide 24

Slide 24 text

24 ローカルで動作できるところまで持っていく

Slide 25

Slide 25 text

25 ローカル環境で動作するところまでもっていく ● 公式推奨の方法でとりあえずやってみた ● rails serverが動くようにした ● rails consoleが動くようにした

Slide 26

Slide 26 text

26 落ちまくるテストをひたすら修正

Slide 27

Slide 27 text

27 落ちまくるテストをひたすら修正 ● 500件ぐらいRspecのテストが落ちてた ● 前半はSyntax的な一つの修正を横展開するだけで数十件ずつ減らせたが、 後半は1件あたりの対応時間が増えていった ○ テストコードを直すべきか、実装を直すべきか ■ 仕様的に正しい挙動とは? ■ そもそもこの機能は生きてるのか? ● 最終的にテストをオールグリーンにするのに1ヶ月以上かかった

Slide 28

Slide 28 text

28 打鍵テスト confidential

Slide 29

Slide 29 text

29 打鍵テスト ● sandbox環境で打鍵テスト ○ 基本的には単体テスト(Rspec)を行なっているため、打鍵テストでは外部 システムとの接続部分を重点的にテスト ● サイトの表示部分以外の機能のテスト ○ バッチ処理 ○ 通知系処理 ■ メール送信 ■ プッシュ送信

Slide 30

Slide 30 text

30 ようやくリリースへ confidential

Slide 31

Slide 31 text

31 リリース ● 新環境用のターゲットグループを作成し、Rails 6環境で構築したEC2 インス タンスをアタッチ ● ロードバランサー(ALB)レベルで Blue/Green デプロイを行った 徐々に割合を上げていく 90% 10%

Slide 32

Slide 32 text

32 アジェンダ ● スペースマーケットのAPI構成について ● 何をやったか ● なぜやったか ● どうやったか ● ふりかえり

Slide 33

Slide 33 text

33 大変だったこと

Slide 34

Slide 34 text

34 ● Rails 4系から6系に上げたので、エラー原因のあたりが付けづらかった ○ Rubyやgemのバージョンアップも一緒にやったのでさらに調査時間が増えてしまった ● バージョンアップは計画的に ○ 「やらないことのリスク」を明確にする ○ 高優先度のタスクとして枠をとってしまう 大変だったこと 一気にいろいろ上げすぎた

Slide 35

Slide 35 text

35 大変だったこと ● DatabaseSelectorを利用した ○ HTTPリクエストがGET/HEADの場合はreadingロールを使う ○ GET/HEAD以外の場合はwritingロールを使う ● controllerのshowメソッド(GET)内にwrite処理が含まれている場合に ReadOnlyエラーが発生して しまう ○ 該当箇所を全てActiveRecord::Base.connected_to(role: :writing) do ~ end ブロックで囲む 必要があった マルチDB接続におけるread処理とwrite処理の適切な振り分け

Slide 36

Slide 36 text

36 まとめ ● メインAPIのRailsのバージョンを4.2から6.0に上げた ○ セキュリティリスクの低減 ○ 開発効率の向上 ○ Railsのメジャーバージョンを2つ上げるのは大変だった ● 事前の断捨離のおかげで影響範囲を縮小でき、結果的に技術的負債を返済 しつつ、トータルの工数を減らすことができた ● バージョンアップは計画的に…😇

Slide 37

Slide 37 text

ご清聴ありがとうございました!