Slide 1

Slide 1 text

© DMM.com 2万rpsを処理する 行動ログ収集システムをGoで作った話 DMM.go #2 1

Slide 2

Slide 2 text

© DMM.com 自己紹介 潮平 諒也 (しおひら まさや) データインフラ部 データエンジニアチーム 高専卒業 -> 19新卒として入社 Go歴 9ヶ月くらい 2

Slide 3

Slide 3 text

© DMM.com 今日お話すること - 行動ログ収集システムのクラウド移行プロジェクト - 配属直後にアサインされて、今年3月の本番リリースまで携わった - Goの経験は研修でTour of Goをさらった程度だった webブラウザから行動ログを受け取るAPIをGoで作成した 3

Slide 4

Slide 4 text

© DMM.com 行動ログ収集システムについて - DMMサイトやアプリユーザの行動を個人に紐づかない形で分析用に追 跡している - 行動ログを受け取り、適切な形に加工して分析基盤へ届ける 4

Slide 5

Slide 5 text

© DMM.com 行動ログ収集システム移行の背景 アプリケーション - 古い - デプロイに半日かかる - 行動ログ収集システムが用途別で2つ存在しており、まとめたい インフラ - セッションを管理しているKVSが増設できない - LBのSSL終端が性能上利用できず、終端サーバを別で用意しており、 こちらのスケールアウトも容易じゃない 5

Slide 6

Slide 6 text

© DMM.com 旧システムの構成図 6

Slide 7

Slide 7 text

© DMM.com 旧トラッキングシステム セッション ユーザの1行動を追うための一意な値 ユーザがページを移動するたびにTTLが更新される TTLが長期・短期の二種類がある 経由情報 どのシステム経由でカートに追加され、商品が購入されたか識別するため の値 7

Slide 8

Slide 8 text

© DMM.com クラウド移行で解決したいこと - トラッキング対象の増加に対応できるようなパフォーマンス - 2万rps以上 - Aerospikeと同等の性能が出るDB - Aerospikeはめちゃくちゃ速い - オンプレに存在するセッション等のデータを引き継がなければいけない 8

Slide 9

Slide 9 text

© DMM.com クラウド移行の課題に対する解決策 - パフォーマンス - APIにGo言語を採用: コンテナネイティブ・速度が出ると噂されている - GKEを採用: 今後増えるサービスを同じ基盤上にのせたかった - DB - DynamoDB or Bigtable -> Bigtable - DynamoDBは料金が高かった - GCP上にシステムを構築することが決定 - セッション等データの引き継ぎ - オンプレ・クラウド両方のDBへ読み書きする並行稼働期間を設けた 9

Slide 10

Slide 10 text

© DMM.com 新システムの構成図 10

Slide 11

Slide 11 text

© DMM.com GCP各リソースの役割 - Pub/Sub - 行動ログのキューイング・一時保存 - Dataflow - JSON -> TSV 変換 - 消費税の計算 - スキーマの変換 - Pub/SubからGCSへのデータ移動 - GCS - 生データの保存 11

Slide 12

Slide 12 text

© DMM.com おまたせしました Goの話です - APMについて - interfaceに依存させてモックできるようにした - パフォーマンスチューニング - まとめ 12

Slide 13

Slide 13 text

© DMM.com APMについて 13

Slide 14

Slide 14 text

© DMM.com APMについて - パフォーマンスチューニングのためにAPIの動きを追跡したい - OpenCensusフレームワークのDatadog Exporterを使用 良かった点 - トラッキングAPI・マイグレーションAPI間を1つのSpanで追跡 - Span: コードを追跡するための1単位 入れ子にできる - 任意のSpan時点でのAPIの状態を表示 14

Slide 15

Slide 15 text

© DMM.com APMについて 15

Slide 16

Slide 16 text

© DMM.com APMの話 16

Slide 17

Slide 17 text

© DMM.com interfaceに依存させてモックで きるようにした 17

Slide 18

Slide 18 text

© DMM.com interfaceに依存させてモックできるようにした - 開発途中は外部依存を生成する場所が散らばっていてモックを使った テストができなかった - コードの構造を変更し、APIの起動時に外部依存を全て生成して後続の 処理に渡すようにした - interfaceを使い、外部依存を使用する処理を隠蔽することでモック化 18

Slide 19

Slide 19 text

© DMM.com 外部依存をまとめたContainerの作成 19 各GCPリソースのクライアント マイグレーションAPIの gRPCクライアント main.goで一度だけ呼び出さ れる

Slide 20

Slide 20 text

© DMM.com プロダクションコードでの処理の提供 20 interface 外部依存を生成しNew関数に渡す 関数はinterfaceを満たした構造体を返す 同じく一度だけ呼び出される

Slide 21

Slide 21 text

© DMM.com テストコードでのモック 21 interfaceで定義され たメソッドを構造体の フィールドとして持つ 構造体を生成する時 に各メソッドの処理を 注入できる

Slide 22

Slide 22 text

© DMM.com テストケースの例 22 前ページの モックで定義した関数の実装

Slide 23

Slide 23 text

© DMM.com モックを用いたテストコード 23 テストケースごとに違う処理を 実装したメソッドを扱える

Slide 24

Slide 24 text

© DMM.com パフォーマンスチューニング 24

Slide 25

Slide 25 text

© DMM.com パフォーマンスチューニング - 負荷試験環境はGoogleから提供されている方法を参考に構築 - https://cloud.google.com/solutions/distributed-load-testing-using-gke - Locust + GKE - 最初の負荷試験ではPodを増やしても3千rps以上数値がでなかった - 横にスケールできない - 目標は2万rps以上捌けて、99パーセンタイルのリクエストに100ms以内 でレスポンスすること - 遠い。。。 25

Slide 26

Slide 26 text

© DMM.com アプローチ - APMを見ると、Bigtableへの読み書きやPub/SubへのPublishが極端 に遅いリクエストがある - 行動ログの保存やセッションの読み書きを見直した 26

Slide 27

Slide 27 text

© DMM.com 試したことその1 27 - Bigtableの読み込みに最新の1データだけを取得するフィルターを追加 した - GCされるまでに時間がかかるため不要な過去のデータまで読んでいた - スキャン量の減少が見込める

Slide 28

Slide 28 text

© DMM.com 試したことその2 - Pub/SubへPublishした際の結果を非同期で受け取るようにした - 結果の応答を待たないことでレスポンス速度の改善を図った 28 Pub/Subへ送信 送信結果の取得

Slide 29

Slide 29 text

© DMM.com いろいろ試した結果 - 速度や捌けるリクエスト数は改善したが目標には遠い - 1万rps程出るようになった - 相変わらずPodを増やしてもパフォーマンスが上がらない うんうん唸っているところにSREの方から一言 「Locust側のPodが偏ってませんか?」 29

Slide 30

Slide 30 text

© DMM.com 原因 - API側・負荷ツール側のPod配置を分散するように設定 - あっさり2万rps以上出た - Pod・Nodeのスケールアウトで性能が向上することも確認 - Pod配置が特定のNodeに偏っていたことが原因 - 主に負荷をかける側 - ネットワークが詰まっていたと思われる 30

Slide 31

Slide 31 text

© DMM.com その後・最終的な構成 その後 - 1Podでどれほどの性能が出るか改めて測定した - リニアに性能がスケールすることを確認した 最終的な構成 - マシンタイプ: n1-standard-8 - 他サービスも同居することを考慮して決定 - ネットワーク帯域幅が下2つのマシンタイプと比べて大きい - Node 18台, Pod 32 31

Slide 32

Slide 32 text

© DMM.com 課題 - JSONのデコードがたまに遅い - デコードだけで数秒かかることがある 原因不明 - たまにgRPC起因のcontext canceledが発生する 原因不明 32

Slide 33

Slide 33 text

© DMM.com まとめ 33

Slide 34

Slide 34 text

© DMM.com まとめ - トラッキングシステムのAPIをGolangで実装しました - ちゃんと期待したパフォーマンスが出た - APMは何かと役に立つので使いこなせると楽 - インフラの設定はちゃんと見直す - 負荷試験の時は負荷ツール側にも目を配る 34