Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
アドフリくんにおけるマイクロサービス間での一貫したトレース実現
Search
gree_tech
PRO
October 17, 2025
Technology
560
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
アドフリくんにおけるマイクロサービス間での一貫したトレース実現
GREE Tech Conference 2025で発表された資料です。
https://techcon.gree.jp/2025/session/TrackB-1
gree_tech
PRO
October 17, 2025
More Decks by gree_tech
See All by gree_tech
多彩なデータに負けないデータ分析パイプライン構築
gree_tech
PRO
0
39
AI駆動で挑むプロダクト刷新 ── アーキテクチャ設計とワークフロー最適化の実践事例 ──
gree_tech
PRO
0
35
『ヘブンバーンズレッド』のリグレッションテストにおけるストーリーの自動プレイ
gree_tech
PRO
0
63
REALITYにTAチームができるまでの軌跡〜ミッション:ガチャ本数5倍に対応せよ!〜
gree_tech
PRO
0
23
イベント続きでもミスらないライブサービスゲーム公式サイト運用システム開発
gree_tech
PRO
0
28
20年間 SNS サービス「GREE」 を支えた技術の刷新と、長期運用サービスの Kubernetes へのリアーキテクト
gree_tech
PRO
0
79
グラフ基盤ワークフローで実現するLLMによる自動ゲームプレイ
gree_tech
PRO
0
49
AIエージェントに脆弱性診断の仕事を奪われかけた ークローリングからコード全診断までの限界突破ー
gree_tech
PRO
0
36
アバター使っておもろいものを作り続けたい
gree_tech
PRO
0
32
Other Decks in Technology
See All in Technology
フィンテック養成勉強会#68
finengine
0
150
オントロジーって 結局なにもの? AI エージェントに「意味」を渡す知識設計の話
greenmidori
0
230
アウトプット初心者、半年間のふりかえり
4o1sobblue
0
440
パスキーの自動テストはどこまでいけるのか
teamlab
PRO
0
280
NDIでApple Vision Proにリアルタイム映像送信
jyouryuusui
0
130
Rust で関数型ドメインモデリング
takonda
0
170
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
0
180
エンタメ企業のM&Aを支えるデータ基盤 ― 統合から店舗のリアルタイム分析まで / Data Engineering Summit 2026
genda
0
200
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
470
10年後、Engineering 行為を剥奪されるとして、わたしたちは、どう、何を創ればいいだろうか。 / If Engineering Is Taken Away in 10 Years, How and What Should We Create?
bitkey
PRO
1
200
[JAWS-UG彩の国埼玉#12]そろそろ準備する?re:Invent2026をやさしく解説 / reinvent2026-sainokuni
sh_fk2
1
360
夫婦で子育てするための育児標準化
codmoninc
PRO
0
460
Featured
See All Featured
Evolving SEO for Evolving Search Engines
ryanjones
0
330
Navigating Team Friction
lara
192
16k
What's in a price? How to price your products and services
michaelherold
247
13k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3.1k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
500
The Curious Case for Waylosing
cassininazir
1
570
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
Side Projects
sachag
456
43k
Faster Mobile Websites
deanohume
310
32k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
380
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
410
Transcript
アドフリくんにおけるマイクロサービ ス間における一貫したトレース実現 - アドフリくんRTBシステムにおけるObservabilityの実装事例 - グリーエックス社 エンジニア 樋口雅拓
樋口雅拓 Go / k8s / RecSys / Android / Kotlin
/ Scala / PHP / Python / Swift / AWS / GCP グリーグループのグリーエックス株式会社で、ソフトウェ ア開発に従事。広告システム開発、GREE Platformの立ち 上げ、不正利用対策、チャットアプリ開発、メディア開発 を経て2025年2月より現職。 グリーエックス社 エンジニア 2
背景と目的 • 複数のマイクロサービスを連携して1つのHTTPリ クエストを処理するシステムを構築した。 • ログやトレース情報がマイクロサービス毎に生成 され、統合して確認することができなかった。 • これを統合して確認できるようにしたため、その 事例について発表する。
発表構成 • 前提知識 ◦ サービス及びシステム概要 ◦ システムの一部であるRTBシステムについて ◦ RTBシステムのObservabilityについて • 提案方式 ◦ 一貫したトレースの実現方法 前提知識を説明した後、提案方式について説明します。 アドフリくん管理画面などRTB以外のサーバー機能、レ ポート機能については、時間の都合で割愛させていただ きます。 3
サービス及びシステム概要 4
アドフリくん - サービス概要 • モバイルアプリ向けの広告配信プラット フォーム • 「動画リワード広告」の取扱量は国内No.1 5 動画リワード広告とは
Pangle/Unity/APP LOVIN/Mintegral/Info Source/AdMob/Digital Turbine/LINE Ads Network/nend/Zucks/ maio/AMoAD
アドフリくん - システム概要 モバイルアプリ向けの広告配信プラットフォーム • メディエーション: 複数のアドネットワークを統合管理 • 収益最適化: リアルタイムでの配信比率調整
• RTB対応: Real-Time Biddingによる高収益化 • 運用効率: 自動化された管理・監視システム 6 アドフリくんは、以下のコンポーネントから構成されています。 • アドフリくんサーバー: 配信設定(利用するアドネットワークのリストや条件)をSDKに伝える。 • アドフリくんSDK: モバイルアプリに組み込み、サーバーから受け取った配信設定に従って広告を取得する。 つまり、アドフリくんはSDKとサーバーが連携して価値を提供しています。 次のスライドでは、アドフリくんサーバーが配信設定を作る方法について説明します。
アドフリくん - SDK概要 • init()で広告設定を読み込みます。 ◦ 広告設定には、アドネットワークの配信比 率や優先順位が含まれています。 • load()で広告を読み込みます。
◦ 配信設定を元に選択されたアドネットワー クに要求します。 • play()で広告を表示します。 7 // SDK初期化 AdfurikunSdk.init(activity) // 広告読み込み AdfurikunSdk.load("REWARD_APP_ID") // 再生準備確認・表示 if (AdfurikunSdk.isPrepared("REWARD_APP_ID")) { AdfurikunSdk.play("REWARD_APP_ID") } 実装例: Android
アドフリくん - アドフリくんサーバー概要 アドフリくんサーバーは、複数のアドネットワークの配信比率を適 切に調整して、収益最大化するものです。 アドフリくんでは、以下3種類に対応しています。 ウォーターフォール配信 優先度を予め設定しておき、その順序で問い合わせる。 一般的に単価が高いDSPほどターゲティングやキャップがキツく、 在庫が少ないため高単価から順番に問い合わせることが合理的。
ウォーターフォールRTBコンビネーション配信 ウォーターフォールとRTBの良い所取りをしたもの。 過去の実績からRTBのeCPMを計算し、ウォーターフォールのeCPM と比較して適切な場所に差し込む。 これにより、確実に高単価が見込めるDSPへの問い合わせをRTBよ り優先させることができる。 8 優先度1: AdMob (eCPM: $5.0) ↓ (広告なし) 優先度2: AppLovin (eCPM: $4.0) ↓ (広告表示) 並列入札: ├─ AdMob: $4.2 ├─ Unity Ads: $4.7 ← 勝者(広告表示) └─ AppLovin: $4.5 RTB (Real-Time Bidding) リクエスト毎にDSPに問い合わせ、最も高い入札額を提示した DSPの広告を配信する。 確実に最高額の広告を表示できるが、仕組みが複雑。 まとめ • ウォーターフォール配信: 対象アプリに最適な配信設定 • RTB: 対象アプリとユーザーに最適な配信設定 • ウォーターフォールRTBコンビネーション配信: 良い所 取り 直感的にはRTBが最適に見えます。 しかし、RTBと通常配信で在庫が分かれているケースが多いた め、組み合わせる事でさらに良い結果を得られる事が多い。 優先度1: AdMob (eCPM: $5.0) ↓ (広告なし) 優先度2: RTB(Unity Ads) (eCPM: $4.7) ↓ (広告表示)
システムの一部である RTBシステムについて 9
RTBシステム RTB機能を提供するシステムです。以下のよう な特徴があります。 ここでは、Observability以外の部分について説 明します。 システム特徴 • 組織: スクラム開発の導入と運用 •
設計: ドメイン駆動設計(DDD)とC4 Modelsによる可視化 • 実装: Clean Architectureの適用とテスト 駆動開発の実践 • 構築: マイクロサービスとして機能ごとに 分離されたサービス群 • 運用: Google Cloud Observabilityを利用 したログ、トレース、メトリックス 10
RTBシステムの特徴 - 組織 スクラム開発の採用 1週間スプリント - 新規技術と不明確な要件への対応 - 素早い学習サイクルの実現 -
課題の早期発見と対応 会議体の制定 - スプリントプランニング: 毎週1時間 - デイリースクラム: 毎日30分 - レトロスペクティブ: 毎週1時間 透明性の向上 - スプリントバックログの可視化 - バーンダウンチャートによる進捗管理 - ステークホルダーとの情報共有 導入効果と課題 メリット - チームコミュニケーションの改善 - 問題解決の文化醸成 - プロジェクト進捗の可視化 - 適切なフィードバックの獲得 デメリット - ベロシティの不安定化 - 中長期スケジュール見積もりの困難 - 会議コストの増加 今後の改善 - 2週間スプリントへの移行を検討 - より安定したベロシティの確立 11
RTBシステムの特徴 - 設計 C4 Modelsは、ソフトウェアアーキテクチャを4つの抽象レベルで表現する設計手法です。 従来のUMLや複雑な設計書に比べ、ステークホルダー全員が理解しややすい図で表現できます。 4階層の構成 • Level 1
(Context): システム全体と外部システムとの関係 • Level 2 (Container): システム内の主要コンポーネントと技術スタック • Level 3 (Component): 各コンテナ内部の詳細設計 • Level 4 (Code): クラス図やシーケンス図レベルの実装詳細 DDDとC4 Modelsの組み合わせにより、複雑なドメインを適切に設計・可視化できます。 チーム全員での設計議論が活発化し、より良い設計につながりました。 12
RTBシステムの特徴 - 実装 Clean Architecture 依存関係の制御 - MVCアーキテクチャの密結合問題解決 - ビジネスロジックの外部技術からの独立
- レイヤー間の責務分離 テスタビリティの向上 - 依存性注入とインターフェース活用 - 外部APIやデータベースのモック化 - 純粋なビジネスロジックのテスト 変更容易性の確保 - 特定層の変更が他層に影響しにくい構造 - データベース変更時のリポジトリ層のみ修正 レイヤー構成と責務 - Controller: HTTP、外部とのデータ変換 - UseCase: ワークフロー、アプリ固有ルール - Entity: ドメインモデル、ビジネスロジック - Repository: DB/APIなど外部技術の詳細実装 依存関係の方向性 13 - 外側の層は内側の層に依存 - 内側の層は外側の層を知らない - インターフェースによる疎結合 Controller → UseCase → Entity
RTBシステムの特徴 - 構築 マイクロサービス 機能ごとにマイクロサービスとして構築してい ます。マイクロサービスには、以下のものがあ ります。 • info API:
SDKからのリクエストを受け、 オークションAPIを使ってオークション処 理を行い、レスポンスを構築する。 • オークションAPI: オークション処理を行 い、広告コンテンツをストレージに保 存。 • Ad API: 広告コンテンツを応答する。 • DSP Notifier: オークション結果をDSPに 通知する。 CI/CDパイプライン GitHubActionsとCloudDeployを利用しています。 14
RTBシステムの Observabilityについて 15
Observabilityの三本柱 📝 ログ (Logs) イベントの詳細情報を記録 • 構造化ログ: JSON形式で の統一 •
コンテキスト: TraceIDと の関連付け • 検索性: クエリによる高速 検索 16 🔍 トレース (Traces) リクエストの流れを追跡 • レイテンシ分析: ボトル ネックの特定 • 依存関係: サービス間の関 係性把握 • エラー伝搬: 障害の原因追 跡 📊 メトリクス (Metrics) システムの健康状態を数値で把握 • エラー率: HTTP 4xx/5xx エラーの割合 • スループット: 秒間リクエ スト数 • リソース使用率: CPU・メ モリ・ネットワーク
Observability - ログ Cloud Logging SDKを利用しています。 これにより、Traceのような直感的なKeyで構造化ログを書き 込むことができます。 (逆に使わない場合、"logging.googleapis.com/trace"と いった分かりづらいKeyが必要。)
17 ## ログ出力例 { "severity": "INFO", "trace": "projects/gree-peridot/traces/37e8e45b2fc23fd035b235bcc3a58555", "spanId": "9fb57bf9f69ab602", "logName": "projects/gree-peridot/logs/info", "jsonPayload": { … }, ... } func (l *LoggingClient) OutputSpan(...) { entry := logging.Entry{ Severity: severity, Trace: fmt.Sprintf("projects/%s/traces/%s", l.projectID, traceID), SpanID: spanID, Payload: payload, } logger.Log(entry) ログパッケージ設計 ログ出力例
Observability - トレース - トレースの各要素は、スパンと呼ばれる。こ のスパンは、実装で範囲を決める。 - ログにtraceIdとspanIdを追加すると、トレー スとログを紐付けることができる。 18
_, span := tracer.Start(ctx, "AuctionEntity", trace.WithSpanKind(trace.SpanKindInternal), trace.WithAttributes( attribute.String("component", "info"), attribute.String("layer", "entity"), ), ) defer span.End() traceID := span.SpanContext().TraceID().String() spanID := span.SpanContext().SpanID().String() e.logger.OutputJsonSpan(..., traceID, spanID, トレーシング実装
Observability - メトリクス - システムメトリクスは自動収集される。 - ビジネスメトリクスは明示的に送信する必要 がある。 19 meter
:= otel.GetMeterProvider().Meter("adfurikun-business") auctionCounter, _ := meter.Int64Counter( "business_auctions_total", metric.WithDescription("Total number of auctions processed"), ) m.auctionCounter.Add(ctx, 1, metric.WithAttributes( attribute.String("auction_type", auctionType), ), ) ビジネスメトリクス実装例
一貫したトレースの実現方法 20
課題: GCPとアプリケーションのトレース連携 Cloud Load BalancingとGKEアプリケーション間のトレース情報の問題 21 Application Span (ルートスパン) ├──
Business Logic Span └── Request └── Other Micro Service └── Business Logic Span Load Balancer Span (見えない) └── Application Span (孤立) ├── Business Logic Span └── Request Other Micro Service └── Business Logic Span 実際の結果 全体のトレースが確認できない。 期待していたトレース RTBシステムは、複数のマイクロサービスを使って HTTPリクエストを処理する。 HTTP Request全体のトレースを確認したい。
解決策1: トレース情報の伝播 トレース情報の伝播はPropagatorの責務。そこで、以下のようにPropagatorを設定。 22 Load Balancer Span (見えない) └── Application
Span (孤立) ├── Business Logic Span └── Request └── Other Micro Service └── Business Logic Span これにより階層構造になったが、ルートスパンが見えないため探しづらい。 X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE HTTP RequestのHeaderに付与されるTRACE_IDがリクエスト側から引き継がれるようになる。 otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( gcppropagator.CloudTraceFormatPropagator{},... )) Load Balancer Spanが見えないのは、Load BalancerがSpan情報をCloud Traceに送信できないため。 それなら、消してしまおう。
解決策2: Load Balancer Spanの削除 // middlewareが生成するスパンにattributeを設定 otelfiber.WithCustomAttributes(func(...) ... { return
[]attribute.KeyValue{ // middlewareで生成するスパンに印をつける attribute.Bool("parent_span_is_lb", true), }}), processors: # otelFiberのMiddlewareで作成したスパンの親スパン IDを削除する transform: trace_statements: - context: span conditions: # 条件に一致するスパンの親スパン ID を持つ場合 - span.attributes["parent_span_is_lb"] == true statements: # 条件に一致するスパンの親スパン ID を削除 - set(span.parent_span_id, SpanID(0x00000)) # span情報を編集したことを記録 - set(span.status.message, "span edited") 23 Application Span (ルートスパン) ├── Business Logic Span └── Request └── Other Micro Service └── Business Logic Span トレース表示 期待通りの表示となった。 OpenTelemetry Collector設定 Application Spanの親スパン情報を消し、ルートスパンと した。 アプリケーション側の実装
OTTL実装の詳細 OTTL構文の解説 バージョン注意点 OTTLの仕様は変更されることがあります 24 よく使用される関数 - set(): 値の設定 -
delete_key(): キーの削除 - replace_pattern(): パターン置換 - truncate_all(): 文字列の切り詰め 主要な構文要素 - context: 処理対象の指定(span, spanevent, metric, log) - conditions: 変換を適用する条件 - statements: 実際の変換処理 transform: trace_statements: - context: span # スパンコンテキスト で処理 conditions: # 条件部分 - span.attributes["parent_span_is_lb"] == true statements: # 実行部分 - set(span.parent_span_id, SpanID(0x00000)) - set(span.status.message, "span edited") 他のプロセッサーとの使い分け - Filter Processor: 単純なフィルタリング - Attributes Processor: 属性の追加・削除 - Transform Processor: 複雑な変換ロジック 用途に応じて適切なプロセッサーを選択することが重要 # v0.120.0以降 processors: transform: trace_statements: - context: span statements: - set(span.parent_span_id, SpanID(0x00000)) # v0.120.0以前 processors: transform: trace_statements: - context: span statements: - set(parent_span_id, SpanID(0x00000))
今後の展望 25
CloudDeployとPrometheusの連携によるカナリアデプロイ 課題 - リスクの高いデプロイ: 一度に全てのトラ フィックが新バージョンに流れる - 障害の影響範囲: 問題発生時に全ユーザーに影 響
- ロールバック時間: 手動での判断と実行が必要 RTBシステム特有の要件 - 低レイテンシ: 50ms以下のレスポンス要求 - 高可用性: 99.9%以上の稼働率必要 - 収益への直接影響: デプロイ失敗が売上に直結 自動判定指標 - エラー率: 0.1%以下を維持 - レスポンス時間: P99で50ms以下 - DSP成功率: 95%以上 - 収益指標: 前バージョン比で5%以上の下落なし 26 現在のデプロイフロー カナリアデプロイフロー
まとめ 27
まとめ • アドフリくんを導入することで、メディアの広告収益を最大化することが できます。 • アドフリくんは、継続的に改善を行う仕組みとなっています。 • 同様の取り組みを行うことで、担当プロジェクトが継続的な改善可能とな ります。 28
ご清聴ありがとうございました 29
None