RTB アプリケーションのベスト プラクティス

このガイドでは、RTB プロトコルに基づいてアプリケーションを開発する際に考慮すべきベスト プラクティスについて説明します。

接続を管理する

接続を維持する

新しい接続を確立すると、既存の接続を再利用する場合よりもレイテンシが増加し、両端でより多くのリソースが必要になります。閉じる接続の数を減らすと、再度開く必要がある接続の数を減らすことができます。

まず、新しい接続を確立するために、追加のネットワーク ラウンド トリップが必要になります。接続はオンデマンドで確立されるため、接続の最初のリクエストは後続のリクエストよりも有効な期限が短く、タイムアウトする可能性が高くなります。さらにタイムアウトが発生するとエラー率が上昇し、ビッダーが抑制される可能性があります。

次に、多くのウェブサーバーが、確立された接続ごとに専用のワーカー スレッドを生成します。つまり、接続を閉じて再作成するには、最終的にリクエストを処理する前に、サーバーがスレッドをシャットダウンして破棄し、新しいスレッドを割り当てて実行可能にして、接続状態を構築する必要があります。これは不必要なオーバーヘッドです。

接続を終了しない

まず、接続の動作を調整します。ほとんどのサーバーのデフォルトは、それぞれ少数のリクエストを行う多数のクライアントが存在する環境に合わせて調整されています。一方、RTB では少数のマシンプールが多数のブラウザに代わってリクエストを送信しますが、これは比較的重要です。このような状況では、接続を何度も再利用するのが合理的です。次の設定をおすすめします。

  • アイドル タイムアウトは 2.5 分です。
  • 可能な限り大きい接続でのリクエスト数の最大数。
  • RAM で対応可能な最大値に対する最大接続数。ただし、接続数がこの値に近づきすぎないように注意する必要があります。

たとえば Apache の場合は、サーバーの種類に依存する値に KeepAliveTimeout を 150、MaxKeepAliveRequests をゼロ、MaxClients を設定する必要があります。

接続動作を調整したら、入札者コードが接続を不必要に閉じないようにする必要もあります。たとえば、バックエンドのエラーやタイムアウトが発生したときにデフォルトの「入札なし」のレスポンスを返すフロントエンド コードがある場合、そのコードが接続を閉じることなくレスポンスを返すようにします。これにより、ビッダーが過負荷状態になり、接続が閉じ始め、タイムアウト回数が増えてビッダーが抑制される状況を回避できます。

接続のバランスを保つ

認定バイヤーがプロキシ サーバー経由でビッダーのサーバーに接続している場合、時間の経過とともに接続のバランスが不均衡になる可能性があります。これは、プロキシ サーバーの IP アドレスのみを知るため、認定バイヤーは各コールアウトを受け取るビッダー サーバーを判別できないためです。時間の経過とともに、認定バイヤーによる接続の確立と終了、そしてビッダーのサーバーが再起動するにつれて、それぞれの接続にマッピングされる接続数が大きく変動することがあります。

一部の接続の使用率が高い場合、その時点で不要なため、開いている他の接続はほとんどアイドル状態のままになる可能性があります。認定バイヤーのトラフィックが変わると、アイドル状態の接続がアクティブになり、アクティブな接続がアイドル状態になる可能性があります。接続のクラスタ化が不十分な場合、ビッダー サーバーでの負荷が不均一になる可能性があります。Google では、リクエストが 10,000 件になるとすべての接続を切断し、時間の経過とともにホット接続を自動的にリバランスすることで、この問題の発生を防ぎます。それでも環境でトラフィックが不均衡になっている場合は、追加の手順を行うことができます。

  1. フロントエンド プロキシを使用する場合は、接続ごとに 1 回ではなく、リクエストごとにバックエンドを選択します。
  2. ハードウェア ロードバランサまたはファイアウォールを介して接続をプロキシし、接続の確立後にマッピングが固定される場合は、接続あたりの最大リクエスト数を指定します。Google ではすでに接続あたりのリクエスト数の上限(10,000 件)を指定しているため、環境でホット接続がクラスタ化している場合にのみ、より厳密な値を指定する必要があります。たとえば、Apache では、MaxKeepAliveRequests を 5,000 に設定します。
  3. ビッダーのサーバーがリクエスト率をモニタリングするように構成し、ピアが一貫して多くのリクエストを処理している場合は、自身の接続の一部を閉じるようにします。

過負荷を適切に処理する

理想的には、ビッダーが処理できるすべてのリクエストを受信できる程度に、割り当てを十分に高く設定し、上限を超えないようにしてください。実際には、割り当てを最適なレベルに維持することは困難であり、さまざまな理由で過負荷が発生します。たとえば、ピーク時にバックエンドが停止する、トラフィック ミックスが変化して各リクエストでより多くの処理が必要になる、割り当て値が大きすぎるなど、さまざまな原因が考えられます。したがって、トラフィックが多すぎた場合にビッダーがどう動作するかを検討することをおすすめします。

リージョン間(特にアジアと米国西部と米国東部と米国西部の間)間の一時的なトラフィック移行(最大 1 週間)に対応するために、7 日間のピークと取引ロケーションごとの QPS の間に 15% の緩和策をおすすめします。

高負荷時の動作は、ビッダーが大まかに次の 3 つのカテゴリに分類されます。

「すべての応答」ビッダー

このビッダーは簡単に実装できますが、過負荷になると最悪の状況になります。受信したすべての入札リクエストに、それが何であれ、すぐに応答できないリクエストをキューに入れて応答しようとします。多くの場合、次のようなシナリオが発生します。

  • リクエスト レートが上がると、すべてのリクエストがタイムアウトするまで、リクエストのレイテンシも増加します。
  • コールアウト率がピークに近づくにつれて急激にレイテンシが上昇
  • スロットリングが行われ、許可するコールアウトの数が急激に減少する
  • レイテンシが回復し始めると、スロットリングが低下する
  • 循環はまた始まります

このビッダーのレイテンシのグラフは、非常に急なのこぎり波のパターンに似ています。あるいは、リクエストがキューに追加された場合、サーバーはメモリのページングを開始するなど、長期的な速度低下を引き起こす何かを実行します。また、ピーク時が過ぎるまでレイテンシはまったく回復しないため、ピーク期間全体のコールアウト率が低下します。いずれの場合も、割り当てを単に低い値に設定した場合よりも、実行または応答されるコールアウトが少なくなります。

「過負荷になったエラー」ビッダー

このビッダーは、一定の割合に達するまでコールアウトを受け付けると、一部のコールアウトでエラーを返すようになります。これは、内部タイムアウト、接続キューイング(Apache の ListenBackLog によって制御)の無効化、使用率またはレイテンシが高すぎる場合に確率論的ドロップモードを実装する、またはその他のメカニズムを介して行うことができます。エラー率が 15% を超えると、スロットリングが開始されます。「すべてに応答する」ビッダーとは異なり、このビッダーは「損失を抑制」するため、リクエスト率が低下してもすぐに回復できます。

このビッダーのレイテンシのグラフは、過負荷時の浅いのこぎり歯のパターンに似ており、最大許容レートの周辺に局所的になります。

「オーバーロード時に入札しない」ビッダー

このビッダーは、一定のレートに達するまでコールアウトを受け入れ、任意の過負荷に対して「入札なし」のレスポンスを返すようになります。「過負荷になるとエラーになる」ビッダーと同様に、いくつかの方法で実装できます。異なる点は Google にシグナルが返されないため、コールアウトの抑制が行われない点です。過負荷はフロントエンド マシンに吸収され、処理可能なトラフィックのみがバックエンドに到達します。

このビッダーのレイテンシのグラフでは、ピーク時にリクエスト率と並行して(人為的に)停止するプラトーと、それに応じて入札を含むレスポンスの割合が低下しています。

次のように、「過負荷時のエラー」と「過負荷時に入札しない」アプローチを組み合わせることをおすすめします。

  • フロントエンドをオーバープロビジョニングして、過負荷時にエラーに設定することで、なんらかの形で対応できる接続数を最大化します。
  • 過負荷でエラーが発生した場合、フロントエンド マシンは返信定型文の「入札なし」を使用してリクエストを解析する必要がありません。
  • バックエンドのヘルスチェックを実装し、十分な容量がない場合は「入札なし」のレスポンスを返すようにします。

これにより、ある程度の過負荷が吸収され、処理可能な数のリクエストにバックエンドが応答できるようになります。これは、リクエスト数が予想よりも大幅に多い場合にフロントエンド マシンが「過負荷時のエラー」にフォールバックする「過負荷状態の入札なし」と考えることができます。

「すべてに応答する」ビッダーがある場合は、実質的に過負荷にならないように接続の動作を調整して、「過負荷時のエラー」ビッダーに変換することを検討してください。これにより、より多くのエラーが返されますが、タイムアウトが短縮され、サーバーがリクエストに応答できない状態にならないようにします。

ping に応答する

ビッダーが ping リクエストに応答できるようにすることは、接続管理自体ではありませんが、デバッグでは驚くほど重要です。Google は ping リクエストを使用して、ビッダーのステータス、接続終了の動作、レイテンシなどのサニティ チェックとデバッグを行います。ping リクエストの形式は次のとおりです。

Google

id: "\3503cg\3023P\364\230\240\270\020\255\002\231\314\010\362\347\351\246\357("
is_test: true
is_ping: true

OpenRTB JSON

"id": "4YB27BCXimH5g7wB39nd3t"

OpenRTB プロトコル バッファ

id: "7xd2P2M7K32d7F7Y50p631"

想定とは違って、ping リクエストには広告スロットは含まれません。また、前述のように、ping リクエストへの応答後に接続を閉じないでください。

ピアリングを検討する

ネットワークのレイテンシまたはばらつきを低減するもう一つの方法は、Google とピアリングすることです。ピアリングは、トラフィックがビッダーに到達するまでの経路を最適化するのに役立ちます。接続エンドポイントは同じままですが、中間リンクは変わります。詳しくは、ピアリング ガイドをご覧ください。ピアリングをベスト プラクティスとして考える理由は、次のとおりです。

  • インターネット上では、トランジット リンクは主に「ホットポテト ルーティング」によって選択されます。これは、パケットを宛先に受信できる、Google ネットワーク外にある最も近いリンクを見つけて、そのリンク経由でパケットをルーティングするものです。多くのピアリング接続があるプロバイダが所有するバックボーンのセクションをトラフィックが通過する場合、選択されるリンクはパケットの開始地点に近い可能性が高いです。その時点を超えてパケットが通過するルートは制御できないため、パケットは途中で他の自律システム(ネットワーク)にバウンスされる可能性があります。

  • ダイレクト ピアリング契約を締結している場合、パケットは常にピアリング リンクに沿って送信されます。パケットの送信元に関係なく、Google が所有またはリースするリンクを通過して、共有ピアリング ポイントに到達します。共有ピアリング ポイントは入札者のロケーションに近い場所であるはずです。その逆の経路は、Google ネットワークへの短いホップから始まり、その後は Google ネットワーク上に留まります。ルートの大部分を Google が管理するインフラストラクチャ上に保持することで、パケットは低レイテンシのルートを経由し、変動の可能性を回避できます。

静的 DNS を送信する

購入者は常に単一の静的 DNS 結果を Google に送信し、トラフィック配信は Google に任せることをおすすめします。

ロード バランシングや可用性の管理を行う際にビッダーの DNS サーバーで行われる一般的なプラクティスを 2 つ紹介します。

  1. DNS サーバーは、クエリに応答して 1 つのアドレスまたはアドレスのサブセットを渡し、このレスポンスをなんらかの方法で巡回します。
  2. DNS サーバーは常に同じアドレスセットで応答しますが、レスポンス内のアドレスの順序は循環します。

1 つ目の手法は、スタックの複数のレベルで多くのキャッシュがあるため、ロード バランシングに適していません。また、Google が DNS 解決時間を入札者に請求するため、キャッシュをバイパスしようとしても望ましい結果が得られない可能性があります。

2 番目の方法では、Google が DNS レスポンス リストから IP アドレスをランダムに選択し、レスポンスの順序は重要ではないため、ロード バランシングはまったく実現されません。

ビッダーが DNS を変更した場合、Google は DNS レコードに設定された TTL(有効期間)に従いますが、更新間隔は不確定のままです。