Upgrade to Pro — share decks privately, control downloads, hide ads and more …

クックパッドの巨大 Rails アプリケーションの改善

hogelog
September 12, 2018

クックパッドの巨大 Rails アプリケーションの改善

hogelog

September 12, 2018
Tweet

More Decks by hogelog

Other Decks in Technology

Transcript

  1. クックパッドの巨大 Rails
    アプリケーションの改善
    クックパッド株式会社 技術部開発基盤 @hogelog (小室直)

    View Slide

  2. hogelog (小室 直)
    ● 2013/8 クックパッド株式会社 入社
    ○ レシピ投稿関連の開発等(Web, Android)
    ○ 会員事業関連、OEM 向け API 開発等 (Web, Android)
    ○ 技術部開発基盤(いろいろ)

    View Slide

  3. 大きな Rails アプリケーション
    開発してますか?

    View Slide

  4. クックパッドでは
    巨大 Rails アプリケーションを
    どう改善しているか

    View Slide

  5. 巨大 Rails アプリケーション
    リポジトリ cookpad_all の今昔

    View Slide

  6. cookpad_all とは
    ● cookpad.com を支える複数の Rails アプリと共有ロジック
    をまとめた shared gem を含むリポジトリ
    ● cookpad_all 内の各アプリはほとんど共有 DB

    View Slide

  7. 一昔前のクックパッドの開発風景
    ● 大多数の社内エンジニアが cookpad_all で開発する状況
    ● 開発基盤、インフラのリソースも cookpad_all に集中
    ○ 強いモノリシック Rails アプリの時代
    ○ The Recipe for the World's Largest Rails Monolith by @a_matsuda
    https://speakerdeck.com/a_matsuda/the-recipe-for-the-worlds-largest-rails-monolith

    View Slide

  8. 2016 年頃のクックパッドの開発風景
    ● Microservices が進み cookpad_all 以外の開発が増える
    ● cookpad_all は巨大だし辛い
    ● cookpad_all は基盤からレガシーな部分が多く整備コストも
    高い
    ○ Microservices 基盤は整っていく
    ○ クックパッドにおける最近のMicroservices事例 by @adorechic
    https://techlife.cookpad.com/entry/2016/03/16/100043

    View Slide

  9. 2017 年、お台場プロジェクト発足
    ● @aamine により立ち上げられた cookpad_all 改善プロ
    ジェクト
    ● 裏の目標は「開発基盤」というチームの解散
    ○ cookpad_all はもうサービス開発チームが高い意識による片手間程度でメ
    ンテナンスできる規模ではない
    ○ cookpad_all を徹底的に改善し、普通の開発チームでメンテナンスできる
    状態にする

    View Slide

  10. お台場プロジェクト
    やったこと

    View Slide

  11. お台場プロジェクトでやったこと
    ● 開発メトリクスの定点観測
    ● システム削除
    ● システム分割
    ● コード削除
    ● その他

    View Slide

  12. 開発メトリクスの定点観測
    ● コード量、起動時間などの開発メトリクスを InfluxDB に記
    録、Grafana のダッシュボードで定点観測
    ○ 大きな Rails アプリケーションをなんとかしよう。まずは計測と可視化からは
    じめよう。 by @hogelog
    https://techlife.cookpad.com/entry/2018/06/08/080000

    View Slide

  13. CI Duration
    ● CI にかかった時間

    View Slide

  14. App Load Time
    ● アプリのロードにかかった時間

    View Slide

  15. Code Statistics
    ● rails stats を記録

    View Slide

  16. 2017-07-01 時点の stats
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Controllers | 55217 | 44464 | 619 | 4505 | 7 | 7 |
    | Helpers | 16853 | 13810 | 21 | 1582 | 75 | 6 |
    | Models | 95824 | 75336 | 1892 | 8854 | 4 | 6 |
    | Mailers | 2011 | 1612 | 45 | 199 | 4 | 6 |
    | Workers | 841 | 712 | 25 | 40 | 1 | 15 |
    | Chanko units | 8656 | 7160 | 2 | 169 | 84 | 40 |
    | Libraries | 50869 | 42003 | 660 | 3779 | 5 | 9 |
    | Feature specs | 58694 | 47269 | 0 | 189 | 0 | 248 |
    | Request specs | 56536 | 48938 | 0 | 24 | 0 | 2037 |
    | Routing specs | 544 | 437 | 0 | 0 | 0 | 0 |
    | Controller specs | 63233 | 52246 | 6 | 123 | 20 | 422 |
    | Helper specs | 5318 | 4389 | 1 | 10 | 10 | 436 |
    | Model specs | 91372 | 75504 | 5 | 85 | 17 | 886 |
    | Worker specs | 1150 | 954 | 0 | 1 | 0 | 952 |
    | Chanko unit specs | 7845 | 6293 | 0 | 8 | 0 | 784 |
    | Library specs | 26156 | 21905 | 23 | 123 | 5 | 176 |
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Total | 541119 | 443032 | 3299 | 19691 | 5 | 20 |
    +----------------------+-------+-------+---------+---------+-----+-------+
    Code LOC: 185097 Test LOC: 257935 Code to Test Ratio: 1:1.4

    View Slide

  17. 2018-09-12 時点の stats
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Controllers | 32080 | 25883 | 305 | 2690 | 8 | 7 |
    | Helpers | 13212 | 10739 | 17 | 1214 | 71 | 6 |
    | Models | 73703 | 58028 | 1282 | 6540 | 5 | 6 |
    | Mailers | 1663 | 1336 | 38 | 165 | 4 | 6 |
    | Workers | 0 | 0 | 0 | 0 | 0 | 0 |
    | Chanko units | 6154 | 5142 | 2 | 147 | 73 | 32 |
    | Libraries | 33604 | 28014 | 373 | 2449 | 6 | 9 |
    | Feature specs | 43505 | 34908 | 0 | 176 | 0 | 196 |
    | Request specs | 809 | 637 | 0 | 0 | 0 | 0 |
    | Routing specs | 406 | 328 | 0 | 0 | 0 | 0 |
    | Controller specs | 48137 | 39729 | 2 | 76 | 38 | 520 |
    | Helper specs | 4151 | 3430 | 0 | 9 | 0 | 379 |
    | Model specs | 63788 | 52339 | 2 | 52 | 26 | 1004 |
    | Worker specs | 0 | 0 | 0 | 0 | 0 | 0 |
    | Chanko unit specs | 2961 | 2359 | 0 | 1 | 0 | 2357 |
    | Library specs | 16383 | 13588 | 17 | 86 | 5 | 156 |
    +----------------------+-------+-------+---------+---------+-----+-------+
    | Total | 340556 | 276460 | 2038 | 13605 | 6 | 18 |
    +----------------------+-------+-------+---------+---------+-----+-------+
    Code LOC: 129142 Test LOC: 147318 Code to Test Ratio: 1:1.1

    View Slide

  18. Dependent Gem Count
    ● 依存 gem 数

    View Slide

  19. GemCollector Up-to-date Point
    ● 依存 gem の最新度
    ○ この gem を使っているアプリケーションを探す by @eagletmt
    https://techlife.cookpad.com/entry/2018/06/08/080000

    View Slide

  20. システム削除
    ● cookpad_all 内の不要なシステムを削除する
    ○ 工夫はとくになし

    View Slide

  21. 2017 年当初の cookpad_all 構成
    ● cookpad というアプリが特に厳しい(1アプリでデプロイ先4つ)

    View Slide

  22. api の削除
    ● cookpad 内のレガシー HTTP API 機能を削除
    ○ 社内でも動作確認不可能な古いモバイルアプリだけから使われていた
    ○ 関係者、責任者と話を詰めて削除

    View Slide

  23. api の削除
    ● cookpad のデプロイ先が1個減る(デプロイ先3つ)

    View Slide

  24. background worker の削除
    ● cookpad 内のレガシー非同期処理システムを削除
    ○ resque 製非同期処理基盤
    ○ モダン非同期処理基盤としては barbeque が整備されていたので移行
    ■ ECS を利用したオフラインジョブの実行環境 by @k0kubun
    https://techlife.cookpad.com/entry/2016/09/09/235007

    View Slide

  25. background worker の削除
    ● cookpad のデプロイ先が1個減る(デプロイ先2つ)

    View Slide

  26. システム分割
    ● システムを正しく分割する
    ● DB 共有はしない。アプリ間は API でやりとりする

    View Slide

  27. pantry の分割
    ● cookpad と pantry を分割 (cookpad_all 内で)
    ○ デプロイ先により挙動が変わる不思議なアプリを分割
    ○ 本質的に共有するものは多くなかった
    (切り離しはもちろん大変だった)

    View Slide

  28. pantry の分割
    ● 1アプリ1デプロイ先という自然な状態に

    View Slide

  29. 様々な Microservices アプリへの切り出し
    ● 検索機能、料理きろく API、モバイルアプリ AB テスト用
    API、ユーザ認証関連機能、など数々なアプリを
    cookpad_all から切り出し
    ○ 切り出す単位は組織構造にフィットする、それでいてひとまとまりになってい
    て細かすぎないサイズ
    ■ つまり「ちょうどいいサイズに」

    View Slide

  30. 様々な Microservices アプリへの切り出し
    ● 色んな機能群を
    Microservices アプリ
    として切り出し

    View Slide

  31. mobile の作り直し
    ● ガラケー向けサイトモバれぴバックエンドのmobile
    ○ アクティブに開発していないので作り直しのブロッカーがいない
    ○ モダンな基盤で作り直す
    ■ Hako (ECS) 環境, gRPC, Service Mesh, ...

    View Slide

  32. mobile の作り直し(移行中)
    ● cookpad_all 内の
    アプリが4つに

    View Slide

  33. コード削除
    ● 不要コードを削除する
    ○ がんばって不要コードを探して削除
    ○ Gemfile をジッと眺めて不要 gem を探す
    ○ lazy loading を利用し不要 gem を検出
    ○ 棚卸し Issue の自動作成
    ○ Iseq 実行処理を記録し不要コードを探す

    View Slide

  34. がんばって不要コードを探して削除
    ● 不要コードをがんばって探して削除する
    ● Code Cleaning Contest を開催
    ○ 期間一ヶ月のコード削除コンテスト
    ○ 掃除にちなんだ豪華景品も

    View Slide

  35. 棚卸し Issue の自動作成
    ● 棚卸し Issue 作成、コード削除うながす作業を(半)自動化
    ○ 不要そうなコードを検出しコミッタからランダムにアサインしてコード削除か
    必要なコードであるか記録するよう促す
    ○ 元データはアクセスログ、バッチ処理実行ログ等
    ● 削除可否だけ聞いてお台場プロジェクトメンバーが削除する
    ことも

    View Slide

  36. Gemfile をジッと眺めて不要 gem を探す
    ● Gemfile を見て不要そうな gem を削除
    ○ jquery-rjs, aws-sdk-v1, ……
    ● 工夫特になし

    View Slide

  37. lazy loading を利用し不要 gem を検出
    ● ruby に手を加え lazy loading 利用し不要 gem を検出
    ○ Ruby の lazy loading の仕組みを利用して未使用の gem を探す by @riseshia
    https://techlife.cookpad.com/entry/2018/04/04/080000

    View Slide

  38. Iseq 実行処理を記録し不要コードを探す
    ● ruby に手を加え Iseq 実行ログを記録し不要コードを探す
    ○ 本番で記録したログを Redshift に蓄積
    ○ 詳細は近日中に @riseshia から techlife かどこかで発表など
    ○ ruby 2.6 では素の ruby で可能になるかも
    ■ Feature #15022 Oneshot coverage by @mame
    https://bugs.ruby-lang.org/issues/15022

    View Slide

  39. その他
    ● gem の更新
    ○ rails, rspec など様々な gem のアップグレード
    ○ Machinist 1 -> FactoryBot 移行
    ○ リポジトリに埋め込まれていた改造 gem を捨てて OSS 最新版に更新
    ○ bootsnap の導入
    ● ruby アップグレード
    ● EC2 インスタンスの式年遷宮 (CentOS 6 -> Ubuntu 16)

    View Slide

  40. うまく進んでいる要因?
    ● 「お台場プロジェクト」という名前をつけた
    ○ 名前があると自分も他人も認識する
    ● 人をアサインしている
    ○ メインタスクとして稼働している優秀なエンジニアが何人もいる
    ● すぐ近くに ruby コミッタが二人いる
    ○ Iseq 実行ログの記録や lazy loading の活用なんかはガッツリサポートして
    もらいました

    View Slide

  41. まとめ

    View Slide

  42. まとめ
    ● とにかく不要なコードを消したり分割したり、やっていってま

    ● まだまだ「ふつうの Rails アプリケーション」とは言えないの
    でチャレンジはいっぱい残されている

    View Slide