MIXI TECH CONFERENCE 2023 にてお話した岡住の資料です。
動画:https://youtu.be/LN28kB3eXXo
https://techcon.mixi.co.jp/d3-1
©MIXI10周年を迎えるモンストサーバコードのRuby及びgemのアップデートにまつわるお話モンスト事業本部 ゲーム運営部モンストサーバ1グループ岡住 和樹
View Slide
©MIXI自己紹介岡住 和樹2019年新卒入社 (4年目)モンスト事業本部 ゲーム運営部 モンストサーバ1グループ機能開発、運用等を担当2
©MIXIはじめに話すこと- 特定のバージョンに関係なく考慮・対応する必要のあった話話さないこと- 具体的なRubyやgemのバージョンに関する話3
©MIXIはじめに前半- モンスターストライク (モンスト) について- サーバチームとサーバコード- APIサーバの構成とデプロイ体制後半- Ruby, gem のアップデートにまつわる話- 様々な問題と工夫- まとめ4
©MIXIモンスターストライクについてひっぱりハンティングRPG誰でも簡単に楽しめる爽快アクションRPG。一緒にいる友だちと最大4人まで同時に遊べる協力プレイ(マルチプレイ)が特徴2023年10月に、10周年を迎える5
©MIXIサーバチームとサーバコード6
©MIXIサーバチームとサーバコード開発体制- 開発・運用の両方を行う- 開発を支援する管理ツールなどの開発も行う- 10~15名程度- オンコール対応 (2名、1週間ローテーション)- サーバコード本体 + 管理ツール etc… のモノレポ (GitHub)- 運用に関するツール類などは、別のモノレポで管理7
©MIXIサーバチームとサーバコードリポジトリの規模感※ コメント行、空行、自動生成コードを除く8リポジトリ全体 Ruby 約40万行 (約7000ファイル)内、RSpec 約25万行本体のコード (Controller, Model) Ruby 約7万行RSpec 約18万行
©MIXIサーバチームとサーバコード次期バージョンへ向けた機能開発※ PR (GitHub Pull Request)9リリース頻度 - 1〜1.5ヶ月- 次期バージョンに関係しないものは逐次リリースリリースタイミング バージョンアップメンテナンス1バージョンあたりの機能開発 PR数 50~100程度ひと月にマージされる PR量 100~200程度
©MIXIサーバチームとサーバコードコードカバレッジ- リポジトリ全体 約90%- 本体 95%以上 (94%のファイルがカバレッジ90%以上)- 計測しているが常に見ているわけではない- 普段から高めていこう!といった活動はしていない10
©MIXIサーバチームとサーバコードコードカバレッジただし・・・- 足りないテストを見つけた時にPRを出す- 簡単な修正でも、可能であればテストは書く- 不具合の修正は、テストで再現させてから- コードレビュー時に、追加してほしいテストケースをコメントする (午後のグループアサインの話もみてね)11
©MIXIAPIサーバの構成とデプロイ体制12
©MIXIAPIサーバの構成とデプロイ体制APIサーバの構成- Unicorn + Padrino + ActiveRecord- OSSをforkしたDB 垂直、水平分散ライブラリ- 数百台のオンプレマシン- App, DB, Memcached, Redis, Resque Worker, …- 様々なキャッシュ- Appサーバ(ローカルファイル、オンメモリ)- Memcached※ 詳しくは https://mixil.mixi.co.jp/culture/16027#monsterstrike13
©MIXIAPIサーバの構成とデプロイ体制APIサーバの構成14App 数百台 Unicorn Worker 数万DB 数百台 数万connectionMemcached 100台弱 キャッシュ量 1TB 以上※ msgpackでシリアライズ済AppDBRedis(Queue)Memcached(Cache)Resqueworker
©MIXIAPIサーバの構成とデプロイ体制デプロイ体制- 定時内なら基本的にいつでも本番デプロイ可能- Capistranoによる手動デプロイ (コマンドを1つ実行する程度)- 容易なgemのアップデート、リファクタリングなどのコード変更は、このタイミングでデプロイ可能15
©MIXIRuby, gemアップデートにまつわる話16
©MIXIRuby, gem アップデートにまつわる話基本方針1. 各種gemのバージョンは、どのRubyバージョンまで対応しているのかを調査する2. 調査結果に応じて、現状のRubyバージョンで上げれるところまでgemのバージョンを上げる3. Rubyと同時に上げる必要のあるgemは、Rubyのバージョンアップと同じタイミングで上げる17
©MIXIRuby, gem アップデートにまつわる話基本方針※ 緊急で対応が必要なものは担当者を決めることもある (先に誰かが動いてることの方が多い )18担当者 明確には決まっていない (率先してやりたい人が担当 )リリース前 (必ず) 開発環境で動作確認 (日々、多くの人が利用している )リリース前(必ずではない)Appサーバ1台〜数台 (全体の数%) にデプロイして動作確認- 意図しないエラーが出ないか- リソースの変化を監視etc…リリースタイミング - 日々のデプロイ- モンストのバージョンアップメンテナンス時
©MIXIRuby, gem アップデートにまつわる話明確な担当者が決まっていない- 期日も決まっていない- 場合によっては、とても時間がかかる(1年ぐらいかかることも)19
©MIXIRuby, gem アップデートにまつわる話明確な担当者が決まっていない少しでもモチベーションを維持するために・・・- 少しでも進捗を出し続けれるように週一30分で進捗共有会をしてる- issueや社内ドキュメントに現状のことや、今後の方針を常にまとめておく (あとから参加したい人が参加しやすいように)20
©MIXI様々な出来事と工夫21
©MIXI大きなgemのアップデート大小様々な問題が起こる- 互換性のない記法- 大量のエラーが発生する- 大量の警告 (warning) が発生する- 依存ライブラリが対応していない- そもそも、テストが実行できないetc…大量のコード修正が必要になることも (100PR以上の修正・・・)22
©MIXI大量のコード修正何はともあれ、まずはテストが実行できるようにする- CIでテストを通過しないとPRはマージ出来ない- テストが通ればそれなりに動く状態を作れる (カバレッジのお陰)23
©MIXI大量のコード修正まずは、テストが実行できるようにする- エラーを修正していく- forkやパッチしているライブラリのコード修正- テスト実行をプロファイリングして実行出来ない理由を探す- gemのコードを読む24
©MIXI大量のコード修正CIでテストを通過しないとPRはマージ出来ない- 実行するテストの範囲を指定するa. 実行範囲を絞る (例: Modelのみ)b. 落ちるテストの一覧を定義して、除外するc. 修正したら、除外リストから消してテストが実行されるようにするd. 修正PRを出すe. 修正が完了したら、実行範囲を広げていく25チームメンバーが修正PRを作りやすい状況を作る
©MIXI大量のコード修正CIでテストを通過しないとPRはマージ出来ない- 次期バージョン開発に影響を及ぼす変更が必要になることもある26以前のバージョンと同様な振る舞いで、コードを書けるようにパッチを当てる(バージョンアップ完了後に撤去する)
©MIXI大量のコード修正修正するコード量を減らす取り組み- 二度と開催されないコードの削除 (コラボなども含む)- 利用されていないコードの削除- 依存gemを減らすGit管理されている & カバレッジが高い→ 気軽に消すことができる27
©MIXI大量のコード修正コードカバレッジの向上- 管理ツール系は、テストがほとんど書かれていなかった28- 最低限のテストを追加した- テストを書くようにコードレビューで声かけていく
©MIXI不具合の発見多くの問題は、CIでテストを実行した際に発見される- それでもコーナーケースな不具合は発生する- 開発環境 で見つかることも多い29修正する際は、必ずテストを足す
©MIXIキャッシュの問題ライブラリのアップデートで、意図せずキャッシュキーが変わる- DBのReadが大量に増える- 場合によっては、DBが耐えられなくなる30キャッシュキーが変わらないようにモンキーパッチ
©MIXIキャッシュの問題アップデート前後でキャッシュの内容が読めなくなる- キャッシュしているオブジェクトの内容が変わったことが原因31事前に、前後で読める形式に変更する→ 新形式でキャッシュをセット + 新・旧形式でキャッシュを読めるようにする
©MIXIメンテナンス前後の不具合一部APIは、メンテナンス実施前のバージョンでもリクエストが来る- サーバとゲームクライアントは、msgpackでやりとりしている- msgpackのアップデート時、互換性がなくエラーが多発した32前のバージョンでリクエストが来る可能性のあるAPIのみ互換性を残す修正をした
©MIXIまとめ- テストの有無でアップデート難易度が大きく変わる- アップデートによって絶対に変わってはいけない挙動を把握しておく- アップデート前後の互換性を意識する- キャッシュキーが変更されていないか- etc…- 継続的にアップデートしていくための仕組みをつくる- チームメンバーが手伝いやすい状況をつくる- 消せるコードを消す- 起こった出来事を記録しておく- 次回のアップデートで参考になる33
©MIXI