明けましておめでとうございます。
バックエンドエンジニアの岡田です。
前回の「広告基盤刷新プロジェクト」はじめましたで、 「バナー広告に関する運用・システム改善」について書いてから、1年以上経ってしまいましたが、
今回は、「広告基盤刷新プロジェクト」の第二弾として、
「ネイティブ広告配信基盤」を内製していることについて書きたいと思います。
対象広告商品
一般的なバナー広告については、前回の記事で書いたように、
Google Ad Manager(以下「GAM」)を利用していますが、
「ネイティブ広告配信基盤」では、ネイティブ広告を対象としています。
ネイティブ広告とは
コンポーネントを組み合わせ、サービスのデザインに合わせることで、
コンテンツと調和し、ユーザエクスペリエンスを向上できる広告フォーマットです。
なぜ作ろうと思ったか
以前、弊社CTOが書いたトクバイにおけるレガシーシステム改善への取り組みにあるように、
運営している主力のサービスであるトクバイのバックエンド/Webサーバーは、モノリシックなRuby on Rails(以下「Rails」)アプリケーションです。
そして、ネイティブ広告に関するシステムも、このモノリシックなRailsアプリケーションに含まれています。
本来、疎結合であるネイティブ広告のシステムも、サービスのビジネスロジックと密結合していき、
新商品や新機能を追加するコストが膨大になるという課題がありました。
そのため、ネイティブ広告のシステムを、モノリシックなアプリケーションから引き剥がし、
新しく「ネイティブ広告配信基盤」を内製することにしました。
GAMのネイティブ広告機能を使わなかった理由
前述したように、一般的なバナー広告については、GAMを利用しているので、
ネイティブ広告でもGAMを利用することを検討しました。
しかし、今後の拡張要件が満たせないと判断し、
ネイティブ広告については、内製することにしました。
機能要件・非機能要件
機能要件としては、
一般的な広告機能要件を満たしているGAMをベンチマークしつつ、
必要最低限の機能を要件としました。
非機能要件としては、大きく下記3つを要件としました。
- 汎用性
- 拡張性
- 速度
汎用性
システムを切り離したからといって、サービスのビジネスロジックと密結合にならない保証はありません。
同じ道を辿らないように、
サードパーティとして公開したり、グループ企業へ導入できるくらい汎用性のある広告基盤にすることを要件としました。
拡張性
新商品や配信制御の新機能、ターゲティング項目の追加などを容易にできることを要件としました。
速度
具体的な数値目標はおいてないですが、
広告配信基盤として、遜色ない速度を要件としました。
全体設計
言語選定
「ネイティブ広告配信基盤」を大きく分けると、
「案件管理アプリケーション」と「配信アプリケーション」があり、
前者をRuby(Rails)、後者をGolangで作ろうと考えていたのですが、
下記により、後者を前者のアプリケーションに同居させ、Ruby(Rails)で作ることにしました。
- サブプロジェクトなので工数が限られ、慣れている言語のほうが開発効率が上がる
- 社内に広告配信基盤の知見があまりない
- ビジネスロジックを固めきれていない部分もあり、当面は試行錯誤が必要
- 「配信機能」をシンプルに切り出していれば、今後Golangへの書き換えも容易である
速度要件に対して
配信時にDBアクセスを行うとボトルネックに成り得るので、
案件情報などのリアルタイム性があまり必要ない情報に関しては、
バッチにて、配信可能な案件情報をs3にアップロードし、
配信サーバーが定期的にダウンロードすることによりDBアクセスを無くしました。
ただ、この方式にすると、
案件の配信開始時刻になっても、案件情報が手元になく、タイムラグが発生してしまうので、
s3には直近配信開始になる案件情報も含めることで対応しました。
また、フリークエンシー制御に使う情報などのリアルタイム性が必要な情報に関しては、
Redisを使うことで、パフォーマンスを下げないようにしました。
負荷テストの結果
負荷テストを実施した結果は、
平均応答速度が15msと、
広告配信基盤として、遜色ない速度にすることができました。
これからについて
この「ネイティブ広告配信基盤」は、まだ本番投入していないですが、
今、企画している新広告商品を、この広告配信基盤で配信し、本番投入しようと考えています。
その後の予定としては、
配信シミュレーション機能などを追加し、
1つの広告商品に関する業務サイクルを一通り回すことを目標としています。
さらに、
既存広告商品の移行や、
Golangへの書き換えも行いたいと考えています。