レート制限

Google では、世界中にいる AdWords API ユーザーの皆様に信頼できるサービスを提供するため、トークン バケット アルゴリズムを使用してリクエストを測定し、1 秒あたりのクエリ(QPS)のレートを判別しています。これは、不正なソフトウェアや制御不能なソフトウェアによって AdWords API サーバーに負荷がかかり、他のユーザーの方に悪影響が及ぶ事態を避けるためです。

たとえば、あるクライアントが意図せず数千のスレッドを立て、同時に複数の AdWords API 呼び出しを行った場合は、サーバーがそれを認識し、RateExceededError を返して呼び出しを行ったソフトウェアにデータ送信の抑制をリクエストします。

レート制限はサーバーの読み込み時間など、いくつかの変数によって変動します。そのため、一定の QPS を提示することはできません。重要なのは、RateExceededError の処理方法を把握し、レート制限を念頭に置いてソフトウェアを開発することです。

このガイドでは RateExceededError の詳細と、レート制限の超過を防ぐ方法について解説します。

新旧バージョンの違い

AdWords API の旧バージョンでは、制限を超えて送信されたリクエストは実行可能な状態になるまで API サーバーのキューに入れられます。そのため、リクエストによっては実行に非常に長い時間がかかります。最新の API では長時間クライアントをブロックするのではなく、直ちに処理を終了して RateExceededError を返します。これは問題を検出し、それに応じてアプリケーションを修正できる重要なフィードバック メカニズムです。

レート制限の種類

AdWords API のクライアント アプリケーションが制御できない要因によって制限を超え、RateExceededError が返されることもありますが、そのような場合にペナルティは生じません。 RateExceededError は一時的なもので、非アクティブな状態が 30 秒続いた後、たいていは自動的に解決されます。

サーバーによって適用されるレート制限にはさまざまな種類があります。クライアント アプリケーションには、クライアント センター(MCC)アカウントの開発者トークンのスコープ内または AdWords アカウントのスコープ内のレート制限が適用されます。各スコープ内では、QPS だけでなく、分単位のリクエスト数や分単位のオペレーション数などによりレート制限が測定されます。これにより、AdWords API は安定したトラフィックと突発的に増加したトラフィックの両方に対応できます。スコープとレート制限の名前は両方とも RateExceededError の一部として返されます。

アクセス権に基づくオペレーション制限

変動しないレート制限は、開発者トークンのアクセス権に基づくオペレーション制限しかありません。アクセス権にはベーシックスタンダードの 2 種類があります。ベーシックのアカウントの場合、オペレーションの上限は 1 日あたり 1 万件、レポートのダウンロードは 1 日あたり 1,000 回となっています。新規に承認された開発者トークンには、デフォルトでベーシックのアクセス権が割り当てられます。1 日に 1 万件を超えるオペレーションを処理したい場合や、1 日に 1,000 件を超えるレポートをダウンロードしたい場合は、AdWords API のお申し込みフォームに必要事項を記入しスタンダードのアクセス権をリクエストしてください。どちらのアクセス権でも料金は発生しません。オペレーションのカウントの仕組みについては、こちらのレート表をご覧ください。

オペレーション以外のレート制限は変動する場合があるため、RateExceededError はアプリケーションで処理することが重要です。

RateExceededError の要素

RateExceededError には 3 つの重要なフィールドがあります。

  • rateScope - 超過したレートのスコープ。値は ACCOUNTDEVELOPER となります。
  • rateName - 超過したレート制限の名前。値は RequestsPerMinute などになります。
  • retryAfterSeconds - リクエストを再試行するまでのアプリケーションの最小待ち時間(秒単位)。待ち時間を指定する際には、retryAfterSeconds にランダムな乗数(1~2 の浮動小数点値など)を適用します。複数のリクエストが同時に送信されるマルチスレッド環境などの場合は、待ち時間の後に新しいリクエストが同時に送信されないようにしてください。

アプリケーションでレート制限の超過が繰り返し起こる場合は、rateScoperateName を確認してより効果的な抑制戦略を導入する必要があります。

アカウントのスコープと開発者のスコープ

rateScope の値は ACCOUNTDEVELOPER となります。これはレート制限が AdWords アカウントのレベルで超過したのか、開発者トークンのレベルで超過したのかによって決まります。

開発者トークンのレートスコープ

AdWords API の利用申し込みを済ませている AdWords MCC アカウントには、それぞれ 1 つの開発者トークンが割り当てられます。大部分のリクエストはこのトークンに関連付けられます。同じ開発者トークンを使用するすべてのクライアント リクエストの QPS が一定のレート制限を超えると、開発者のレートスコープを示す RateExceededError が返される場合があります。

たとえば MCC アカウントで 100 個の AdWords アカウントを管理している状況で、クライアント ソフトウェアの複数のインスタンスが同じ開発者トークンを使用し、複数のプロセス、スレッド、コンピュータに渡って 1 秒あたり数百件のリクエストを送信した場合、そのクライアント ソフトウェアには開発者トークンのレートスコープを示す RateExceededError が返されます。

アカウントのレートスコープ

MCC アカウントで管理している 1 つの AdWords アカウントで、同じアプリケーションにより 1 秒あたり多数のリクエストが送信される場合は、アカウントのスコープ内でレート制限が超過したことを示す RateExceededError が AdWords API サーバーから返される場合があります。たとえばクライアント アプリケーションで複数のスレッドが生成され、1 つの AdWords アカウントの制限を超える mutate() オペレーションが実行された場合に、このようなエラーが返されます。

アカウントのレートスコープにおけるこのレート制限は、リクエストの送信にどの開発者トークンが使用されたかに関係なく、1 つの AdWords アカウントに送信されたすべてのリクエストが対象となります。

たとえば 1 つの AdWords アカウントが 5 つの MCC アカウントで管理されている場合は、5 つすべての MCC アカウントが同じ AdWords アカウントに対して同時にリクエストを送信する可能性があります。すべての MCC アカウントの合計の QPS が制限を超過すると、クライアントにはアカウントのレートスコープの RateExceededError が返されます。

レートの名前とその重要性

レートスコープの仕組みだけでなく、超過したレート制限の種類を把握することも重要です。レート制限の種類は rateName フィールドに返されます。次のような名前のレート制限がよく使用されます。

  • RequestsPerMinute
  • OperationsPerMinute
リクエストとオペレーションの違い

RequestsPerMinuteOperationsPerMinute には、どのような違いがあると思いますか。SOAP サービスの呼び出しは、すべてリクエストとしてカウントされます。たとえば CampaignService.mutate() を呼び出すと、そのたびに 1 回のリクエストとしてカウントされます。ただし mutate リクエストでは、100 件の CampaignOperation を渡したと仮定すると、100 件のオペレーションとしてカウントされます。

上述の例では、複数のオペレーションを 1 件のリクエストにまとめて RequestPerMinute のレート制限超過を防いだとしても、OperationsPerMinute のレート制限に達してしまいます。

その他のオペレーションがカウントされる仕組みについては、レートシートをご覧ください。

特殊なケースについて

上記のレート制限は一般的なものですが、他の種類のレート制限を超えてしまう場合もあります。そのような場合は、AdWords API のフォームからお知らせください。

低減策

アプリケーションが RateExceededError を受信した場合は、低減策を講じることをおすすめします。低減策を講じないと、アプリケーションがエラーから回復するまでさらに長い時間がかかってしまいます。最も簡単なのは、RateExceededError.retryAfterSeconds の値を考慮してリクエストを再試行するか、他のリクエストを続行することです。

たとえば Java の場合、スレッドを一時停止してから別のリクエストを処理するには Thread.sleep() を用いるのが簡単です。

try {
  ...
} catch (ApiException e) {
  for (ApiError error : e.getErrors()) {
    if (error instanceof RateExceededError) {
      RateExceededError rateExceeded = (RateExceededError) error;
      Thread.sleep(rateExceeded.getRetryAfterSeconds() * 1000);
    }
  }
  ...
}

この方法は簡単ですが、スループット全体を改善する次善策であり、最後の手段として使用することをおすすめします。

レート制限の超過リスクは多くの方法で低減できます。メッセージングや再配信、スロットリングといったエンタープライズ統合パターン(EIP)の概念を理解すれば、より安定性の高いクライアント アプリケーションを構築できるようになります。

これから、そうした方法の推奨例を見ていきます。なお、低減策を講じたとしても、RateExceededError を処理できるようにしておくことの重要性は変わりません。

制御

リクエストの件数を減らし、クライアント側から QPS を抑制すれば、アプリケーションを制御して RateExceededError を極力低減することができます。

推奨される方法は以下のとおりです。複雑さの順に並んでおり、下のものほど安定性と精度が高くなっています。

  • 同時並行スレッドを制限
  • リクエストを一括処理
  • BatchJobService を使用
  • スロットリング / レート リミッター
  • リクエストを複数のアカウントにインターリーブ
  • キューを使用
  • 新規アカウントと既存アカウントを区別

同時並行スレッドを制限

クライアント アプリケーションが必要以上のスレッドを生成し、すべてのスレッドが同時に AdWords API を呼び出すことが RateExceededError の主な原因です。クライアント アプリケーションが生成できる同時並行スレッドの数に制限はありませんが、非常に多くのスレッドによってリクエストが同時に送信されると、開発者トークンで設定されている 1 秒あたりのリクエスト数の上限を簡単に超えてしまいます。

同時並行でリクエストを送信するスレッド数については、プロセスや機器全体で適切な上限を設けることをおすすめします。そのうえで上方修正を重ねていけば、レート制限を超過せずにスループットを最適化できます。

また、スレッド全体を対象にクライアント側から QPS を抑制する方法もご検討ください(スロットリング / レート リミッターを参照してください)。

リクエストを一括処理

複数のリクエストはなるべく一括処理することをおすすめします。この方法は mutate() の呼び出しで特に有効です。たとえば AdGroupAd の複数のインスタンスでステータスを更新する場合は、AdGroupAd ごとに mutate() を呼び出すのではなく、mutate() を 1 回だけ呼び出し複数の AdGroupAdOperation をまとめて渡すことができます。他の例やオペレーションの効果的なまとめ方については、推奨例をご覧ください。

複数のオペレーションを 1 つのリクエストにまとめる場合は、リクエスト全体が処理されるか、完全に失敗するかのいずれかの結果になります。1 つのオペレーションが失敗するとリクエスト全体が失敗し、何も更新されません。こうした性質は部分障害処理を利用することで変えることができます。

また、リクエストの一括処理ではリクエストの件数を減らし、1 分ごとのリクエスト数のレート制限を低減することができますが、1 つのアカウントに対して多数のオペレーションを実行すると、1 分ごとのオペレーション数のレート制限に達してしまう場合があります。

BatchJobService を使用

ジョブが長時間実行される場合や、多数のオペレーションを処理する場合、あるいは多数のオペレーションが複数のサービスにまたがっている場合は、BatchJobService を使用することをおすすめします。BatchJobService では、Google のクラウド内で数千件のオペレーションのスケジュールを設定し、非同期で実行できます。必要な作業は、結果を分析してジョブが完了したかどうかを確認することだけです。

詳細については、一括処理ガイドをご覧ください。

スロットリング / レート リミッター

クライアント アプリケーションのスレッド数を制限する以外に、クライアント側にレート リミッターを導入することも可能です。この手法では、プロセスやクラスタのすべてのスレッドに対し、クライアント側から特定の QPS 制限を適用することができます。

具体的には Guava レート リミッターを導入することや、クラスタ環境向けにトークン バケットベースの独自のアルゴリズムを導入することができます。たとえばトークンを生成し、データベースなどの共有トランザクション ストレージに保管することができますが、その場合、各クライアントはトークンを取得しないとリクエストを処理できません。トークンがなくなった場合、クライアントは次のトークンが生成されるまで待機する必要があります。

ほとんどの場合、開発者トークンのスコープのレート制限はスロットリングによって超過を回避することができます。

リクエストを複数のアカウントにインターリーブ

アカウントのスコープでレート制限を超過する場合は、クライアント側でアカウントの QPS にレート制限を課すことができますが、数千のアカウントを管理している場合は手間がかかります。そうした場合は、アカウントを基準にリクエストをインターリーブすると簡単です。

たとえば 10 個のアカウントで 5,000 件の mutate() オペレーションを実行する場合は、一括処理したオペレーションを 1 回目はアカウント 1、その次はアカウント 2、そしてアカウント 3 のように順番に送信することができます。具体的には次のようなプロセスが実施されます。

  1. アカウント 1 の 500 件の mutate オペレーションを送信する(5,000 件なので 10 回繰り返す)
  2. アカウント 2 の 500 件の mutate オペレーションを送信する(これも 10 回繰り返す)
  3. …(10 個のアカウントが終わるまでこの繰り返し)

この方法はシンプルですが、1 分あたりのオペレーション数でアカウントのスコープのレート制限を超える場合があります。

アカウントをインターリーブすると、リクエストは次のように処理されます。

  1. アカウント 1 の 500 件の mutate オペレーションを送信する
  2. アカウント 2 の 500 件の mutate オペレーションを送信する
  3. アカウント 3 の 500 件の mutate オペレーションを送信する
  4. …(10 個のアカウントが終わるまでこの繰り返し)
  5. アカウント 2 の 500 件の mutate オペレーションを送信する
  6. アカウント 2 の 500 件の mutate オペレーションを送信する
  7. …(すべてのアカウントの 5,000 件のオペレーションが完了するまで繰り返す)

この例では、アカウントを基準にリクエストをインターリーブする方法を紹介していますが、BatchJobService がご自分の状況に適しているかどうかを確認することも重要です。詳細については一括処理ガイドをご覧ください。

キューを使用

オペレーションの負荷を分散し、リクエストとコンシューマーのレートを管理する場合は、メッセージ キューを使用するのが得策です。オープンソースのものから商標権があるものまでさまざまなメッセージ キューがあり、その大部分は複数の言語に対応しています。

メッセージ キューを使用すると、複数のプロデューサーからキューにメッセージがプッシュされ、複数のコンシューマーがそれらのメッセージを処理します。同時並行のコンシューマー数を制限してコンシューマー側にスロットルを導入するか、プロデューサーかコンシューマーのどちらかにレート リミッターまたはスロットラーを導入することができます。

たとえばメッセージ コンシューマーが RateExceededError を受信した場合、そのコンシューマーはリクエストをキューに再び戻して処理を再試行できます。このコンシューマーはそれと同時に、エラーから回復するまで数秒間処理を停止するよう、すべてのコンシューマーに通知することもできます。

新規アカウントと既存アカウントでキューまたはレート リミッターを区別

キューやレート リミッターを導入する場合は、既存の AdWords アカウントより新しいアカウントの方が、大幅に厳しいレート制限(低い QPS)が課される場合があることに注意してください。新しいアカウントを定期的に作成しながら古いアカウントも大量に管理している場合は、2 種類のアカウントでそれぞれ異なるレート リミッターまたはスロットルを使用すると効果的です。

これにより、QPS が低いアカウントに制限されることなく両方のアカウントでスループットを最大化できます。

通常、新しい AdWords アカウントに対する制限は、そのアカウントで広告が公開されると緩和されていきます。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。