Slide 1

Slide 1 text

©MIXI 10周年を迎えるモンストサーバコードの Ruby及びgemのアップデートにまつわるお話 モンスト事業本部 ゲーム運営部 モンストサーバ1グループ 岡住 和樹

Slide 2

Slide 2 text

©MIXI 自己紹介 岡住 和樹 2019年新卒入社 (4年目) モンスト事業本部 ゲーム運営部 モンストサーバ1グループ 機能開発、運用等を担当 2

Slide 3

Slide 3 text

©MIXI はじめに 話すこと - 特定のバージョンに関係なく考慮・対応する必要のあった話 話さないこと - 具体的なRubyやgemのバージョンに関する話 3

Slide 4

Slide 4 text

©MIXI はじめに 前半 - モンスターストライク (モンスト) について - サーバチームとサーバコード - APIサーバの構成とデプロイ体制 後半 - Ruby, gem のアップデートにまつわる話 - 様々な問題と工夫 - まとめ 4

Slide 5

Slide 5 text

©MIXI モンスターストライクについて ひっぱりハンティングRPG 誰でも簡単に楽しめる爽快アクションRPG。一緒にいる友だちと最大4人ま で同時に遊べる協力プレイ(マルチプレイ)が特徴 2023年10月に、10周年を迎える 5

Slide 6

Slide 6 text

©MIXI サーバチームとサーバコード 6

Slide 7

Slide 7 text

©MIXI サーバチームとサーバコード 開発体制 - 開発・運用の両方を行う - 開発を支援する管理ツールなどの開発も行う - 10~15名程度 - オンコール対応 (2名、1週間ローテーション) - サーバコード本体 + 管理ツール etc… のモノレポ (GitHub) - 運用に関するツール類などは、別のモノレポで管理 7

Slide 8

Slide 8 text

©MIXI サーバチームとサーバコード リポジトリの規模感 ※ コメント行、空行、自動生成コードを除く 8 リポジトリ全体 Ruby 約40万行 (約7000ファイル) 内、RSpec 約25万行 本体のコード (Controller, Model) Ruby 約7万行 RSpec 約18万行

Slide 9

Slide 9 text

©MIXI サーバチームとサーバコード 次期バージョンへ向けた機能開発 ※ PR (GitHub Pull Request) 9 リリース頻度 - 1〜1.5ヶ月 - 次期バージョンに関係しないものは逐 次リリース リリースタイミング バージョンアップメンテナンス 1バージョンあたりの機能開発 PR数 50~100程度 ひと月にマージされる PR量 100~200程度

Slide 10

Slide 10 text

©MIXI サーバチームとサーバコード コードカバレッジ - リポジトリ全体 約90% - 本体 95%以上 (94%のファイルがカバレッジ90%以上) - 計測しているが常に見ているわけではない - 普段から高めていこう!といった活動はしていない 10

Slide 11

Slide 11 text

©MIXI サーバチームとサーバコード コードカバレッジ ただし・・・ - 足りないテストを見つけた時にPRを出す - 簡単な修正でも、可能であればテストは書く - 不具合の修正は、テストで再現させてから - コードレビュー時に、追加してほしいテストケースをコメントする (午後 のグループアサインの話もみてね) 11

Slide 12

Slide 12 text

©MIXI APIサーバの構成とデプロイ体制 12

Slide 13

Slide 13 text

©MIXI APIサーバの構成とデプロイ体制 APIサーバの構成 - Unicorn + Padrino + ActiveRecord - OSSをforkしたDB 垂直、水平分散ライブラリ - 数百台のオンプレマシン - App, DB, Memcached, Redis, Resque Worker, … - 様々なキャッシュ - Appサーバ(ローカルファイル、オンメモリ) - Memcached ※ 詳しくは https://mixil.mixi.co.jp/culture/16027#monsterstrike 13

Slide 14

Slide 14 text

©MIXI APIサーバの構成とデプロイ体制 APIサーバの構成 14 App 数百台 Unicorn Worker 数万 DB 数百台 数万connection Memcached 100台弱 キャッシュ量 1TB 以上 ※ msgpackでシリアライズ済 App DB Redis (Queue) Memcached (Cache) Resque worker

Slide 15

Slide 15 text

©MIXI APIサーバの構成とデプロイ体制 デプロイ体制 - 定時内なら基本的にいつでも本番デプロイ可能 - Capistranoによる手動デプロイ (コマンドを1つ実行する程度) - 容易なgemのアップデート、リファクタリングなどのコード変更は、この タイミングでデプロイ可能 15

Slide 16

Slide 16 text

©MIXI Ruby, gem アップデートにまつわる話 16

Slide 17

Slide 17 text

©MIXI Ruby, gem アップデートにまつわる話 基本方針 1. 各種gemのバージョンは、どのRubyバージョンまで対応しているのか を調査する 2. 調査結果に応じて、現状のRubyバージョンで上げれるところまでgem のバージョンを上げる 3. Rubyと同時に上げる必要のあるgemは、Rubyのバージョンアップと 同じタイミングで上げる 17

Slide 18

Slide 18 text

©MIXI Ruby, gem アップデートにまつわる話 基本方針 ※ 緊急で対応が必要なものは担当者を決めることもある (先に誰かが動いてることの方が多い ) 18 担当者 明確には決まっていない (率先してやりたい人が担当 ) リリース前 (必ず) 開発環境で動作確認 (日々、多くの人が利用している ) リリース前 (必ずではない) Appサーバ1台〜数台 (全体の数%) にデプロイして動作確認 - 意図しないエラーが出ないか - リソースの変化を監視 etc… リリースタイミング - 日々のデプロイ - モンストのバージョンアップメンテナンス時

Slide 19

Slide 19 text

©MIXI Ruby, gem アップデートにまつわる話 明確な担当者が決まっていない - 期日も決まっていない - 場合によっては、とても時間がかかる(1年ぐらいかかることも) 19

Slide 20

Slide 20 text

©MIXI Ruby, gem アップデートにまつわる話 明確な担当者が決まっていない 少しでもモチベーションを維持するために・・・ - 少しでも進捗を出し続けれるように週一30分で進捗共有会をしてる - issueや社内ドキュメントに現状のことや、今後の方針を常にまとめて おく (あとから参加したい人が参加しやすいように) 20

Slide 21

Slide 21 text

©MIXI 様々な出来事と工夫 21

Slide 22

Slide 22 text

©MIXI 大きなgemのアップデート 大小様々な問題が起こる - 互換性のない記法 - 大量のエラーが発生する - 大量の警告 (warning) が発生する - 依存ライブラリが対応していない - そもそも、テストが実行できない etc… 大量のコード修正が必要になることも (100PR以上の修正・・・) 22

Slide 23

Slide 23 text

©MIXI 大量のコード修正 何はともあれ、まずはテストが実行できるようにする - CIでテストを通過しないとPRはマージ出来ない - テストが通ればそれなりに動く状態を作れる (カバレッジのお陰) 23

Slide 24

Slide 24 text

©MIXI 大量のコード修正 まずは、テストが実行できるようにする - エラーを修正していく - forkやパッチしているライブラリのコード修正 - テスト実行をプロファイリングして実行出来ない理由を探す - gemのコードを読む 24

Slide 25

Slide 25 text

©MIXI 大量のコード修正 CIでテストを通過しないとPRはマージ出来ない - 実行するテストの範囲を指定する a. 実行範囲を絞る (例: Modelのみ) b. 落ちるテストの一覧を定義して、除外する c. 修正したら、除外リストから消してテストが実行されるようにする d. 修正PRを出す e. 修正が完了したら、実行範囲を広げていく 25 チームメンバーが修正PRを作りやすい状況を作る

Slide 26

Slide 26 text

©MIXI 大量のコード修正 CIでテストを通過しないとPRはマージ出来ない - 次期バージョン開発に影響を及ぼす変更が必要になることもある 26 以前のバージョンと同様な振る舞いで、コードを書けるようにパッチを当てる (バージョンアップ完了後に撤去する)

Slide 27

Slide 27 text

©MIXI 大量のコード修正 修正するコード量を減らす取り組み - 二度と開催されないコードの削除 (コラボなども含む) - 利用されていないコードの削除 - 依存gemを減らす Git管理されている & カバレッジが高い → 気軽に消すことができる 27

Slide 28

Slide 28 text

©MIXI 大量のコード修正 コードカバレッジの向上 - 管理ツール系は、テストがほとんど書かれていなかった 28 - 最低限のテストを追加した - テストを書くようにコードレビューで声かけていく

Slide 29

Slide 29 text

©MIXI 不具合の発見 多くの問題は、CIでテストを実行した際に発見される - それでもコーナーケースな不具合は発生する - 開発環境 で見つかることも多い 29 修正する際は、必ずテストを足す

Slide 30

Slide 30 text

©MIXI キャッシュの問題 ライブラリのアップデートで、意図せずキャッシュキーが変わる - DBのReadが大量に増える - 場合によっては、DBが耐えられなくなる 30 キャッシュキーが変わらないようにモンキーパッチ

Slide 31

Slide 31 text

©MIXI キャッシュの問題 アップデート前後でキャッシュの内容が読めなくなる - キャッシュしているオブジェクトの内容が変わったことが原因 31 事前に、前後で読める形式に変更する → 新形式でキャッシュをセット + 新・旧形式でキャッシュを読めるようにする

Slide 32

Slide 32 text

©MIXI メンテナンス前後の不具合 一部APIは、メンテナンス実施前のバージョンでもリクエストが来る - サーバとゲームクライアントは、msgpackでやりとりしている - msgpackのアップデート時、互換性がなくエラーが多発した 32 前のバージョンでリクエストが来る可能性のある APIのみ互換性を残す修正をした

Slide 33

Slide 33 text

©MIXI まとめ - テストの有無でアップデート難易度が大きく変わる - アップデートによって絶対に変わってはいけない挙動を把握しておく - アップデート前後の互換性を意識する - キャッシュキーが変更されていないか - etc… - 継続的にアップデートしていくための仕組みをつくる - チームメンバーが手伝いやすい状況をつくる - 消せるコードを消す - 起こった出来事を記録しておく - 次回のアップデートで参考になる 33

Slide 34

Slide 34 text

©MIXI