Slide 1

Slide 1 text

サーバーサイドの開発言語を C# から Go へ置き換えた道のり 株式会社IRIAM 江口 達郎 飯塚 直亮

Slide 2

Slide 2 text

アジェンダ 本日お話しすること ● 前編 (飯塚) ○ Go ポーティングを行おうとした経緯 ○ Go を採用した経緯 ○ Go 未経験者が Go を使用してみた感想 ○ ポーティングしたことのメリット ● 後編 (江口) ○ C# から Go へコードのポーティングの進め方 ○ 本番環境での C# から Goへの切り替え方 ○ Go を採用したことによるメリット 2

Slide 3

Slide 3 text

自己紹介 飯塚 直亮 (Naoaki Iizuka) IRIAM事業部 エンジニアリング部 エンジニアリング第一グループ ● 2016 年ソーシャルゲーム会社に新卒入社 ○ ブラウザゲームのサーバーサイド担当 ● 2019 年に IRIAM に入社 ○ アプリのサーバーサイド担当 ○ 2022 年から GL に就任 ○ 現在はアプリや管理画面開発、マネジメント業務関連に従事 経歴 その他 3 ● 一番好きなしらすは「ゆきんこしらす」(写真のやつ)

Slide 4

Slide 4 text

IRIAMについて IRIAM(イリアム)は、スマホひとつで いつでも・どこでも「キャラクターのライブ配 信」を楽しめるアプリです。

Slide 5

Slide 5 text

5 Go ポーティングを行おうとした経緯

Slide 6

Slide 6 text

Go ポーティングを行おうとした経緯 6 アプリケーションコードを網羅的に理解できるメンバーが不在 C# でサービスを成長させるためのメンバーが不在

Slide 7

Slide 7 text

アプリケーションコードを網羅的に理解できるメンバーが不在 ● コードの属人化 ○ 現存メンバーが触ったことないコードが存在 ○ 設計思想が闇の底 ● その結果、気軽にコード変更ができない ○ コードの関連性を理解できていないのでコア実装を変えられない ○ 機能追加などに多大なコストがかかる ○ 設計レベルから改修を行えない 7

Slide 8

Slide 8 text

● 知見不足 ○ 社内でなかなか知見が湧いてこない状況になってしまった ○ ライブラリや言語バージョンのキャッチアップに疎くなってしまった ○ コードの保守性を高められない ● サービス規模を拡大できない ○ サービスのフェーズに応じて臨機応変に対応できない C# でサービスを成長させるためのメンバーが不在 8

Slide 9

Slide 9 text

Go ポーティングを行おうとした経緯 9 「アプリケーションコードを網羅的に理解できるメンバーが不在」 ● 知見不足 ● サービス規模を拡大できない ● コードの属人化 ● 気軽にコード変更ができない 「C# でサービスを成長させるために必要なメンバーが不在」

Slide 10

Slide 10 text

ポーティングを行うことで…!!! 10 アプリケーションコードを網羅的に理解できるメンバーが不在 ● ポーティング先の言語の有識者が居るので知見共有が行われるはず! ● コードを再生成しているので将来リファクタリングしたい放題なはず! ● 全コードを読む必要があるのでどのコードでも少なくとも一人は理解者が生まれるはず! ● コード変更時に聞ける人が生まれるはず! C# でサービスを成長させるために必要なメンバーが不在

Slide 11

Slide 11 text

11 Go を採用した経緯

Slide 12

Slide 12 text

Go を採用した経緯 12 「社内に有識者が居た」 「ポーティング後の未来との相性がよかった」 「メンバーのモチベーションが高かった」

Slide 13

Slide 13 text

● 設計ベースからサービスを作れる ○ 0 からの作り直しが発生するので必要不可欠 ● キャッチアップのアンテナ ○ 言語のバージョンアップに対してアンテナを張れた ● ティーチングの体制 ○ プルリクエストでコードレベルを上げられる ○ 未経験者が多い中で、みんなで学習していくという体制が作れた ○ 技術選定に対して適切な議論が行える 社内に有識者が居た 13

Slide 14

Slide 14 text

● GCP との相性 ○ google 系のサービスを入れる時にハードルが低い ○ 公式ライブラリが充実している ● 今後採用していく技術との相性 ○ 後述にあるので割愛 ポーティング後の未来との相性がよかった 14

Slide 15

Slide 15 text

● みんなで学習する ○ わからないをしっかり共有して教え合う ○ とにかくわからないことを恥じることはない ● チーム文化が良かった ○ 議論をして色々決めていく文化が ○ 知見を一人のものにしないでみんなのものにする メンバーのモチベーションが高かった 15

Slide 16

Slide 16 text

Go を採用した経緯 16 「社内に有識者が居た」 ● GCP のサービスとの相性が良かった ● 後述するポーティング後を考えた時に Go を採用した方がメリットがあった ● 設計から実装まで整理し直せるメンバーが居た ● Go 未経験のメンバーに対してティーチングできる体制できた 「ポーティング後の未来との相性がよかった」 ● Go を勉強するというモチベーションと環境があった ● なんだかんだポーティングする上でここが重要だったかも 「メンバーのモチベーションが高かった」

Slide 17

Slide 17 text

17 Go 未経験者が Go を触ってみて

Slide 18

Slide 18 text

ポーティング前のメンバーのステータス 18 iizuka ● C#, PHP でゲームのバックエンド開発を行なっていた ● Go 触ってみたいけど機会がなかった ● C# でゲームのバックエンド開発を行なってた ● Go…?あぁ、マスコットが可愛い言語だね! サーバーエンジニア A ● C# でゲームのバックエンド開発を行なってた ● Go という名前は知ってたぐらい サーバーエンジニア B

Slide 19

Slide 19 text

みんながまずやったこと… 19

Slide 20

Slide 20 text

A Tour of Go 20

Slide 21

Slide 21 text

● 自分で書いたツールを Go で書き直してみる ○ 身近なところで手を動かす ● 他人のコードをレビューする ○ 人のコードを読んで自分の意見を述べる ○ 生まれた議論から学習する ● とにかく有識者に聞く ○ これはとても大事! その他には 21

Slide 22

Slide 22 text

実際に Go を触ってみての所感 22 ● 言語仕様がシンプル ○ A Tour of Go やれば大まかコードが読める ○ 一つの実装の仕方に複数パターン記法が存在しない ○ 誰が書いても同じコードになる ● 動かしやすい ○ 環境構築がラクラク ○ サクッと試せるのがコスト安くて good ● 便利標準ライブラリが少ない印象 ○ LINQ みたいな便利標準ライブラリがない

Slide 23

Slide 23 text

23 ポーティングを行ったメリット

Slide 24

Slide 24 text

ポーティングを行ったメリット 24 「コード文化を再制定できた」 ● 言語のこだわりが減って幅が広がる ● ただ熱量にはこだわって組織文化は崩さなかった ● チーム内でポリシーを再制定 ● linter と formatter の力を借りてさらに強化! 「エンジニア採用の幅が広がった」

Slide 25

Slide 25 text

25 Go ポーティングプロジェクトについて

Slide 26

Slide 26 text

自己紹介 江口 達郎 (Tatsuro Eguchi) IRIAM事業部 エンジニアリング部 エンジニアリング第一グループ ● 大手SI会社を経てスマートフォン向けゲーム業界に転職 ● 新しい分野に挑戦したいと考え2020年よりライブ配信プラット フォームのIRIAMに入社 ● 現在はIRIAMでサーバーサイドの負債返済や配信周りのシステム 設計・実装に従事 経歴 26

Slide 27

Slide 27 text

APIサーバー Google Kubernetes Engine Go ポーティングプロジェクトについて IRIAM のインフラ構成 27 配信サーバー Compute Engine バッチサーバー Compute Engine Cloud DNS Cloud Load Balancing Cloud SQL Memorystore

Slide 28

Slide 28 text

APIサーバー Google Kubernetes Engine Go ポーティングプロジェクトについて C# から Go への置き換え対象 28 配信サーバー Compute Engine バッチサーバー Compute Engine Cloud DNS Cloud Load Balancing Cloud SQL Memorystore Goへの置き換え対象

Slide 29

Slide 29 text

大まかなスケジュール 29 Go ポーティングプロジェクトについて 2020年10月 2022年7月 Web API Go化に着手 Web API置き換え完了 2023年1月 バッチ置き換え完了 2022年3月 Web API ポーティング完了 バッチ Go化に着手 2022年10月 バッチ ポーティング完了 12月 Web API Go側へ置き換え開始 明確な完了期限は切らずにとにかくポーティングを終わらせる

Slide 30

Slide 30 text

30 C# から Go への置き換えにあたってのルール

Slide 31

Slide 31 text

C# から Go への置き換えにあたってのルール 31 ● リファクタは極力しない 忠実に挙動をGoに置き換えるためにリファクタせずにポーティングす る。レビューする際にも比較しやすく ● クライアントに迷惑をかけない リクエストやレスポンスの内容、APIで処理する内容を一切変えない

Slide 32

Slide 32 text

C# から Go への置き換えにあたってのルール 32 ● 機能開発は継続して行う IRIAMの新機能や既存機能の改修は止めずに継続して行う ● テストをしっかり書く ポーティングが正しくできていることを確認するためにもテストを しっかり書くことをルールづけた

Slide 33

Slide 33 text

33 C# から Go への置き換えの準備

Slide 34

Slide 34 text

C# から Go への置き換えの準備 34 本番環境で呼ばれているAPIを列挙 ⇦ DBに入っているアクセスログから列挙 調査の結果 150 APIほどあった

Slide 35

Slide 35 text

C# から Go への置き換えの準備 35 クライアントチームで各APIを調査して追記 呼んでいるAPIパス 呼んでいる画面や タイミング 呼んでいる目的

Slide 36

Slide 36 text

36 C# から Go へのポーティングの進め方

Slide 37

Slide 37 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 ● サーバーメンバー数人で頑張る ● APIサーバーを作る足がかりから着手 ○ C#固有の機能 (DateTime.Ticksなど) のGo化 ○ ユーザー認証機能などのミドルウェア層のGo化 37 まずはポーティングのための足固めを行った

Slide 38

Slide 38 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 ● ポーティング専属のメンバーを配置 ○ ポーティングを行うAPIが150近くありバッチも数十件あり膨大 ○ ポーティング関連の作業だけを行う ● メンバーが増えてポーティングのプルリクが大量に積まれる ○ レビューがたまる ○ レビューだけを行うメンバーを配置 38 ポーティングのためのリソースを大幅に割いた

Slide 39

Slide 39 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 ● ポーティングを進める管理者をおいた ○ ポーティングするAPIの割り当て管理 ○ レビューまで完了したAPIのデバッグ依頼 ○ 開発デプロイ、本番デプロイなどのポーティング状態管理 39 ポーティング専属人数が最大で5人くらいいたのでしっかり管理

Slide 40

Slide 40 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 割り当て管理はNotionで実施 40 進行状況一覧

Slide 41

Slide 41 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 ● ポーティングするものの割り当て方を工夫 ○ なるべく機能的に遠いものを順次割り当てるようにした ■ DBアクセスのコードを重複してポーティングしてしまわないように ○ 開発中の機能に関わりそうなAPIのポーティングは避ける ■ 開発は継続して行われている ■ ポーティング+機能追加の形にした 41 なるべく無駄な割り当てが出ないように細かく管理

Slide 42

Slide 42 text

C# から Go へのポーティングの進め方 最初期〜初期〜中期〜後期 ● ポーティングが終わるのか不安になる 42 最後は 気合い と 根性

Slide 43

Slide 43 text

43 本番環境での Go への切り替え

Slide 44

Slide 44 text

本番環境での Go への切り替え (API編) C# と Go のどちらにルーティングするかを決める NGINX を中間に置いた 44 C# APIサーバー Google Kubernetes Engine 配信サーバー Compute Engine Cloud DNS Cloud Load Balancing Cloud SQL Memorystore Go APIサーバー Google Kubernetes Engine ルーティング用に新設 NGINX

Slide 45

Slide 45 text

45 ● サービスは止めず、運用したままで切り替わる 利用者が少ない昼間の時間帯に切り替える ● ルーティングを切り替えるだけで Go 側にリクエストが行く 挙動がおかしいなどを観測したら、ルーティングを戻すだけで切り戻し完了 本番環境での Go への切り替え (API編) ● APIの切り替えは少しずつ行う 一気に切り替えると影響範囲が読めなくなる。ゆっくり確実に切り替える。

Slide 46

Slide 46 text

● 本番APIの切り替え時にアナウンス Slackの全体チャンネルで報告。おかしな挙動がないかチェックしてもらう意味も ● 大きいAPIはメンテナンス中に切り替える ギフト送信APIなどは問題が発生した際の影響が大きい。メンテ中に最終チェックを行った 46 本番環境での Go への切り替え (API編) ↑ このような感じで全体に周知

Slide 47

Slide 47 text

Go 版のバッチサーバー C# 版のバッチサーバー 本番環境での Go への切り替え (バッチ編) バッチに関してはC#からGoに置き換えるタイミングで実装方法を見直した 47 バッチサーバー Compute Engine dll バッチサーバー Cloud Run HTTPサーバー Cloud Scheduler cron ● バッチサーバーが固定インスタンスだったので増強が難しい ● 定期実行の失敗・成功などがGCP管理画面上でわかるようになった

Slide 48

Slide 48 text

本番環境での Go への切り替え (バッチ編) 1. Goのコードをデプロイ 2. バッチサーバーのcronを停止(C#) 3. Cloud Scheduler を設定(Go) 48 ○ 毎分動作するバッチ: メンテナンス中に切り替え ○ 上記以外: バッチが動作する間の時間に切り替え 置き換えルール C#→ Goへの切り替え方

Slide 49

Slide 49 text

49 切り替えにより生まれたメリット

Slide 50

Slide 50 text

切り替えにより生まれたメリット 50 ● Web APIの応答速度はそこまで変わらなかった Goになったからと言って早くはならなかった ● C#からGoに切り替えたことによる性能劣化はなかった 切り替え前に負荷試験を実施。負荷試験は Locust + boomer で実施 ● CI/CD の導入が進んだ GitHub Actionsでの自動テスト、自動ビルド、自動デプロイ化が進み楽に

Slide 51

Slide 51 text

切り替えにより生まれたメリット 51 ● テストを書く文化が定着した 全体のカバレッジは55%程度だが、C#時代のほぼ0%からは大幅なカバレッジ向上 ● 未使用のコード・APIが無くなった ポーティング時点で使われているコードのみをGoに置き換えたのでスリムになった 開発者体験は大幅に向上した

Slide 52

Slide 52 text

52 切り替え完了、その先へ

Slide 53

Slide 53 text

切り替え完了、その先へ 53 ● 将来的には HTTP/1.1 でのリクエストから gRPC へ ● ① の対応はこの前哨戦的な位置付け pb化 gRPC化 ● APIを改修するタイミングでリクエスト、レスポンスの形式を変更 ● JSONでのデータのやり取りから pb でデータをやりとりするように ① HTTP/1.1 + JSON → HTTP/1.1+ Protocol Buffers へ ② HTTP/1.1 + pb → gRPC へ

Slide 54

Slide 54 text

54 まとめ

Slide 55

Slide 55 text

まとめ 55 「C#からGoへ開発言語を置き換えたメリットは大きかった」 ● 専用の工数を割り当てても長期プロジェクトになることは覚悟する必要がある ● 長期プロジェクトになるので最後は「気合い」 ● 単体テストとデバッグをしっかり行ったので障害はほとんどなかった ● 問題があった際もすぐに切り戻せるようにしておいた ● シンプルな言語なのでC#からの移行は難しくなかった ● エンジニア採用面でのメリットも大きかった 「IRIAMの全API、バッチをGoに置き換えるには2年以上かかった」 「少しずつ切り替えていく」

Slide 56

Slide 56 text

56