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

大規模プラットフォームにおけるGoの利用例 DMM.go#4

大規模プラットフォームにおけるGoの利用例 DMM.go#4

「DMM.go」と題して、DMM GroupにおけるGoの勉強会を開催しています。
DMM.go #4の中で大規模プラットフォームにおけるGoの利用例について話したスライドになります。

Jyashin

May 19, 2022
Tweet

More Decks by Jyashin

Other Decks in Programming

Transcript

  1. © 2020 EXNOA LLC 大規模プラットフォームにおけるGoの 利用例 DMM.go #4 EXNOA プロダクト本部

    プラットフォームマイグレーション部 SREチーム 2021.05.18
  2. © 2020 EXNOA LLC • 岡崎 翔悟(Okazaki Shogo) • 合同会社

    EXNOA • プロダクト本部 プラットフォームマイグレーション部 SREチーム • 17新卒として入社(5年目) • 愛称は邪神 • DMM.goの登壇2回目 • 前回:DMM.go #2 2 自己紹介
  3. © 2020 EXNOA LLC プラットフォームの概要 ゲームプラットフォームのWebシステム • 一般的なWebサービス ◦ HTMLを返す

    • ゲームデベロッパー向けのAPI ◦ 課金や会員等のプラットフォーム機能の提供 • ゲーム自体のサーバーは別 5
  4. © 2020 EXNOA LLC プラットフォームの特徴 特徴 • 高負荷 ◦ トップページ:最大1000

    rps ◦ ゲーム実行画面:数万 rps ▪ 時期や時間帯で差が激しい。過去最大で10万 rps • スパイク傾向が強い ◦ ヒットタイトルのリリース時やイベント開始時 ◦ 深夜0時のログインボーナス狙い 6
  5. © 2020 EXNOA LLC リプレイス要因 • 全体的なシステムの老朽化 • 画面主導なリポジトリ構成 ◦

    ドメイン駆動設計できていない • モノリシックな開発では限界 ◦ マイクロサービス化しないと成長できない段階 • フロントエンドとバックエンドが密結合 • クラウド移行を進めたい 7
  6. © 2020 EXNOA LLC 解決手法 • コンテナ化 ◦ Docker •

    コンテナオーケストレーションツールの利用 ◦ Kubernetes • マイクロサービス化 ◦ フロントとバックエンドの分離、画面主導からの脱却 • ドメイン駆動設計 ◦ マイクロサービスの粒度や依存関係を適切に保つ 8
  7. © 2020 EXNOA LLC アーキテクチャ • Kubernetes(EKS)で水平スケーリング • API Gatewayを設けて、認証・認可が

    各ドメインに散らからないように • フロントとバックエンドを分離して、 GraphQLでスキーマ駆動 • Goの採用箇所 ◦ Kong API GatewayのPlugin ◦ バックエンドAPI 10
  8. © 2020 EXNOA LLC Kong API GatewayのPlugin • API GatewayとしてKongを採用

    ◦ その拡張PluginをGoで作成している • Pluginがやっていることは認証・認可サー バーに通信するだけ • 認証・認可APIもGo製 ◦ 後述するバックエンドAPIと構成は一緒 12
  9. © 2020 EXNOA LLC バックエンドAPI • フロントが必要な情報をJSONで返すAPI • ビジネスロジックを担う •

    DBや外部APIからの情報取得を担う • 図中では1つですが、複数サービス存在し ます 13
  10. © 2020 EXNOA LLC トップページ負荷試験のPod数 • トップページのリプレイスをするにあたって負荷試験を行った ◦ 1000rps耐えるPod数を明らかにする試験 ←

    今回お話します ◦ 平常時の推測である300rps〜600rpsの試験 • 負荷のシナリオ(1000rps) ◦ ウォームアップ:4分 ◦ 最大負荷:14分 ◦ クールダウン:2分 • 1000rpsの定義 ◦ 画面へのリクエストです 15
  11. © 2020 EXNOA LLC 1Podのリソース Go製API 16 • requests: •

    cpu: 500m • memory: 512Mi • limits: • cpu: 1000m • memory: 1024Mi Next.js製Webサーバ • requests: • cpu: 1000m • memory: 512Mi • limits: • cpu: 2000m • memory: 1024Mi
  12. © 2020 EXNOA LLC 1000rpsでのPod数:API Gateway, Go製API • Kong ◦

    16 Pod • 認証・認可API ◦ それぞれ 20 Pod • ゲーム情報取得API ◦ 8 Pod • その他バックエンド(10サービス) ◦ それぞれ 4 Pod 17
  13. © 2020 EXNOA LLC 1000rpsの負荷試験をやってみて • Go製APIは非常に安定していた ◦ パフォーマンスチューニングは一切せずに済んだ ◦

    バイナリファイルを置くだけなので、スケールアウトも早い • 最初にリクエストを受けるWebサーバはかなりPodが必要 ◦ 性質上、スケールアウトに時間がかかってしまうのがネック • BFFも複数のバックエンドに通信をする必要があるのでPodが必要 ◦ キャッシュが非常に有効だった Podを並べておけばかなりの負荷に耐えられることがわかった 19
  14. © 2020 EXNOA LLC 実際の運用時のPod数は? • 実際に1000rpsにいくことは非常に稀 ◦ 社会現象レベルの大ヒットタイトルが出た瞬間くらい ◦

    それでも平常時に数百rpsは出る • 日中→ピークタイム→深夜0時 を上手く乗り越えられるか ◦ 実際に運用して調整していく予定 ◦ オートスケーリングで安定したままPodを増減させられる範囲を探っていく • Podの起動スピードはかなり重要 ◦ 早く起動ができるほど、急なスパイクに耐えることができる ◦ Goはやはり相性が良さそうで、特に手間がかからなかった ◦ Next.js製Webサーバの方はチューニングが必要そうである 20
  15. © 2020 EXNOA LLC SREとして • 前回と比べて、SREとして品質担保をする側になった ◦ 人が書いたコードをレビューする方が多くなった ◦

    プロジェクトテンプレートの保守・運用 ◦ 品質担保のリファクタリング ◦ セキュリティ周りの対応 ◦ バージョン更新 ◦ linterの管理 ◦ アーキテクチャ決定 ◦ 学習サポート 22
  16. © 2020 EXNOA LLC 前回お話したGoを使った開発(1/2) • 言語として提供されるフォーマット ◦ 複数人開発で、書き方での差分が出ないのでとても良い •

    言語として提供されるパッケージ管理 ◦ Go Modules 便利 • 後方互換性の高さ ◦ ちゃんと互換性を持ったマイナーバージョンアップ • 学習コストの低さ ◦ Go自体を覚えるのはそう難しくない(と思う) ◦ 難しいのは設計やアーキテクチャ、ドメイン分析… 23
  17. © 2020 EXNOA LLC 実際に運用してどうだったか(1/2) • 言語として提供されるフォーマット ◦ SREとしてみるとすごい助かる •

    言語として提供されるパッケージ管理 ◦ Go Modules 便利。パッケージの更新もしやすい • 後方互換性の高さ ◦ 非常に更新しやすい! ◦ 本番もちゃんと1.18になっています • 学習コストの低さ ◦ Goの書き方がわからないという質問を受けたことはなかった ◦ 難しいのは設計やアーキテクチャ、ドメイン分析なのはやはりそうだった 24
  18. © 2020 EXNOA LLC 前回お話したGoを使った開発(2/2) ◦ 多種多様なアーキテクチャから選定しないといけない場合が増えた ▪ メリットを享受できないのにフルスタックなフレームワークを使うと困る ◦

    RDB以外にもいろんなDBが使える時代 ▪ Amazon DynamoDB, Cloud Spanner, etc. ◦ 分散システムが(つらいけど)手軽に利用できる時代 ▪ Amazon Kinesis, Apache Kafka, etc. ◦ フロントエンドとバックエンドの分離 ▪ バックエンドは単に永続層からデータを取ってフロントにデータを渡すだけにしたい 25
  19. © 2020 EXNOA LLC 実際に運用してどうだったか(2/2) ◦ 多種多様なアーキテクチャから選定しないといけない場合が増えた ▪ フルスタックのフレームワークではなく、必要なGoパッケージをクリーンアーキテクチャでシンプル に使っていくことで、開発者の学習コストを下げられた

    • SREをやってわかったが、他人のコーディング力を上げるのは難しすぎる ▪ プロジェクトテンプレートが使いまわせ、様々なアーキテクチャに対応できた ▪ BatchをGoで書いてKubernetesのCronJobで動かしたりもできた ◦ RDB以外にもいろんなDBが使える時代 ◦ 分散システムが(つらいけど)手軽に利用できる時代 ▪ 実際に全文検索が強いものが欲しくなったりした ▪ Redis Streamを使う検討を始めた ▪ これもクリーンアーキテクチャで差し替えられる構造が役に立った ◦ フロントエンドとバックエンドの分離 ▪ バックエンドの言語としてGoを採用してメリットが多かった 26
  20. © 2020 EXNOA LLC まとめ(1/2) • プラットフォームの特徴と負荷傾向 ◦ ゲームという性質上、平常時の負荷とピーク時の差が激しい ◦

    スパイクもかなり激しい ◦ ヒットタイトルが生まれることはチャンスだが同時にピンチでもある • 最大1000rpsのトップページを捌くアーキテクチャ ◦ バックエンドAPIの言語としてGoが存在 ◦ オートスケーリングと相性の良いGoの特性 ◦ その他、Kubernetes等のGoで作られたエコシステムに支えられている 28
  21. © 2020 EXNOA LLC まとめ(2/2) • バックエンドAPIの言語にGoを選択して良かったと思えた ◦ それなりの開発規模で組織としてビジネスに対応していく必要がある現場でメリッ トがあると思う

    ▪ シンプルなことを積み上げていくことで着実に成果を出す ◦ 開発のレベルに差があるのは常なので、それをサポートできるかが肝 ▪ CIでgolagci-lintを利用することで、品質を保つこともしている • WebサービスはAPIだけでは成り立たない ◦ フロントエンドが必要 ▪ 画面を担うため、どうしても重くなりがち ◦ だからこそ、安定かつ高速なバックエンドAPIが必要ともいえる 29
  22. © 2020 EXNOA LLC 質問への回答(1/2) • 標準パッケージしか使っていない? ◦ 3rd製パッケージも普通に使っています ◦

    例:WebフレームワークとしてEchoを採用 • Echoの採用理由ってある?(Ginとの比較とか) ◦ 決定メンバーが詳しくて他と比べても内容に遜色はないので採用 ▪ はっきり技術的な理由があるわけではない ◦ Ginとは性能で比較したわけではない ▪ Echoだとこんな感じで捌けたという一例だと思っていただければ ◦ 非常にシンプルな使い方をしているので、困っていないという側面 ▪ どういう構成なのかで選択するフレームワークも変わってくると思います 32
  23. © 2020 EXNOA LLC 質問への回答(2/2) • 負荷試験環境って存在する? ◦ 1000rps相当の強い負荷試験をするために作成しました ◦

    STG環境で済む場合はSTGでやることもあります • 負荷の掛け元は別? ◦ 別のECSから負荷試験を実行しています ◦ 通信の経路も本番と同じになるような構成にしている 33