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

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

接続を管理する

接続を維持する

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

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

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

接続を閉じないようにする

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

  • アイドル タイムアウトを 2.5 分に短縮。
  • 接続あたりの最大リクエスト数を可能な限り高い値に設定します。
  • 最大接続数を RAM が処理できる最大値に設定します。ただし、接続数がその値に近づきすぎないように注意してください。

たとえば、Apache では、KeepAliveTimeout を 150、MaxKeepAliveRequests をゼロ、MaxClients をサーバータイプに応じた値に設定する必要があります。

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

接続のバランスを保つ

認定購入者がプロキシ サーバー経由でビッダーのサーバーに接続する場合、プロキシ サーバーの IP アドレスしかわからないため、認定購入者はどのビッダー サーバーが各コールアウトを受信しているかを判断できず、接続のバランスが崩れる可能性があります。時間の経過とともに、オーソライズド バイヤーが接続を確立して閉じ、ビッダーのサーバーが再起動されると、それぞれにマッピングされる接続の数は大きく変動する可能性があります。

一部の接続が大量に使用されている場合、開いている他の接続は、その時点では必要ないため、ほとんどアイドル状態のままになることがあります。認定購入者のトラフィックが変化すると、アイドル状態の接続がアクティブになり、アクティブな接続がアイドル状態になることがあります。接続が適切にクラスタ化されていない場合、ビッダー サーバーに負荷が偏る可能性があります。Google は、10,000 件のリクエスト後にすべての接続を閉じて、ホット接続を時間の経過とともに自動的に再バランス調整することで、この問題を回避しようとしています。それでも環境でトラフィックのバランスが崩れる場合は、次の手順を試してください。

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

過負荷を適切に処理する

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

リージョン間(特にアジアと米国西部、米国東部と米国西部)で一時的なトラフィックのシフト(最大 1 週間)に対応するには、7 日間のピークと取引拠点あたりの QPS の間に 15% の緩衝を設定することをおすすめします。

負荷が高い場合の動作について、ビッダーは大きく 3 つのカテゴリに分類されます。

「すべてに応答」するビッダー

実装は簡単ですが、過負荷になるとパフォーマンスが最も低下します。どのような状況でも、受信したすべての入札リクエストに応答しようとします。すぐに処理できないリクエストはキューに追加されます。通常、次のようなシナリオが発生します。

  • リクエスト レートが増加すると、すべてのリクエストがタイムアウトするまで、リクエストのレイテンシも増加します。
  • コールアウト率がピークに近づくにつれてレイテンシが急増する
  • スロットリングが開始され、許可されるコールアウト数が大幅に減少する
  • レイテンシが回復し始め、スロットリングが緩和される
  • サイクルが再び始まります。

このビッダーのレイテンシのグラフは、非常に急な鋸歯状のパターンに似ています。キューに追加されたリクエストにより、サーバーがメモリのページングを開始したり、長期的な速度低下を引き起こすその他の処理を開始したりすることもあります。ピーク時間帯が終わるまでレイテンシがまったく回復しないため、ピーク期間全体でコールアウト率が低下します。どちらの場合も、割り当てを低い値に設定した場合よりも、コールアウトの発生数や応答数が少なくなります。

「エラー オン オーバーロード」ビッダー

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

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

「過負荷時に入札しない」ビッダー

このビッダーは、一定のレートでコールアウトを受け入れてから、過負荷が発生すると「入札単価なし」のレスポンスを返します。「エラー オン オーバーロード」ビッダーと同様に、これはさまざまな方法で実装できます。異なる点は、Google にシグナルが返されないため、コールアウトがスロットリングされることがないことです。オーバーロードはフロントエンド マシンによって吸収され、フロントエンド マシンが処理できるトラフィックのみをバックエンドに転送します。

このビッダーのレイテンシのグラフは、ピーク時にリクエスト レートと(人為的に)並行して増加しなくなる平坦な部分と、それに伴う入札を含むレスポンスの割合の低下を示しています。

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

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

これにより、一部の過負荷を吸収し、バックエンドが処理できるリクエスト数に正確に対応できるようになります。これは「過負荷時に入札しない」と見なすことができます。リクエスト数が想定よりも大幅に多い場合、フロントエンド マシンは「過負荷時にエラー」にフォールバックします。

「すべてに応答」する入札者を使用している場合は、接続動作を調整して、過負荷を拒否するようにし、「過負荷時にエラー」を返す入札者に変更することを検討してください。これにより、返されるエラーが増えますが、タイムアウトが短縮され、サーバーがリクエストに応答できない状態になるのを防ぐことができます。

ピアリングを検討する

ネットワーク レイテンシや変動を減らすもう 1 つの方法は、Google とピアリングすることです。ピアリングを使用すると、トラフィックがビッダーに到達する経路を最適化できます。接続エンドポイントは同じですが、中間リンクは変更されます。詳細については、ピアリング ガイドをご覧ください。ピアリングをベスト プラクティスと見なす理由は次のとおりです。

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

  • 一方、直接ピアリング契約が締結されている場合、パケットは常にピアリング リンク経由で送信されます。パケットの送信元に関係なく、パケットは Google が所有またはリースしているリンクを通過して、共有ピアリング ポイントに到達します。このピアリング ポイントはビッダーの場所の近くにある必要があります。帰路は、Google ネットワークへの短いホップから始まり、残りのルートでは Google ネットワークに留まります。ルートの大部分を Google が管理するインフラストラクチャに維持することで、パケットが低レイテンシ ルートを使用するようにし、潜在的な変動を回避します。

静的 DNS を送信する

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

入札者の DNS サーバーがロード バランシングやアベイラビリティの管理を行う際に、よく使用される 2 つの方法を以下に示します。

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

最初の手法は、スタックの複数のレベルでキャッシュが大量に使用されるため、ロード バランシングに適していません。また、キャッシュをバイパスしても、Google はビッダーに DNS 解決時間を請求するため、優先結果が得られない可能性があります。

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

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