レートに関する上限

Google Ads API は、リクエストをクライアントのお客様 ID(CID)と開発者トークンごとに秒間クエリ数(QPS)でバケット化します。つまり、メータリングは CID と開発者トークンの両方に対して独立して適用されます。Google Ads API は、トークン バケット アルゴリズムを使用してリクエストを測定し、適切な QPS 上限を決定します。そのため、正確な上限は、常にサーバー全体の負荷によって異なります。

レート制限を課す目的は、1 人のユーザーが(意図的にまたは意図せずに)大量のリクエストで Google Ads API サーバーに負担をかけて、他のユーザーのサービスを妨げることがないようにすることです。

レート制限に違反しているリクエストは、RESOURCE_TEMPORARILY_EXHAUSTED というエラーで拒否されます。

リクエスト数の積極的な削減とクライアント側からの QPS のスロットリングの両方を行うことで、アプリを制御し、レート制限を緩和できます。

レート制限を超える可能性を減らす方法はいくつかあります。メッセージング、再配信、スロットリングなどのエンタープライズ インテグレーション パターン(EIP)のコンセプトに精通することで、より堅牢なクライアント アプリを構築できるようになります。

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

同時並行タスクを制限する

レート制限を超える根本的な原因のひとつは、クライアントのアプリケーションが過剰な数の並列タスクを生み出していることです。クライアント アプリケーションに並列リクエストの制限数はありませんが、開発者トークン単位で 1 秒あたりのリクエスト数の制限を簡単に超えることになります。

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

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

一括処理リクエスト

複数のオペレーションを 1 つのリクエストにまとめることを検討してください。これは、MutateFoo 呼び出しに最もあてはまります。たとえば、AdGroupAd の複数のインスタンスのステータスを更新する場合は、AdGroupAd ごとに MutateAdGroupAds を 1 回呼び出すのではなく、MutateAdGroupAds を 1 回呼び出して複数の operations を渡すことができます。その他の例については、バッチ オペレーションのガイダンスをご覧ください。

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

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

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

Guava レート リミッターを確認できます。また、クラスタ環境用にトークン バケット ベースの独自のアルゴリズムを実装することもできます。たとえば、トークンを生成してデータベースなどの共有トランザクション ストレージに保存することもできます。その場合、各クライアントはリクエストを処理する前にトークンを取得して消費する必要があります。トークンを使い切ると、クライアントは次のトークンのバッチが生成されるまで待機することになります。

キューを使用する

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

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

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