GCP で 429 エラーが発生した場合、これはリクエストレート制限(Rate Limiting)に達したことを意味します。Google Cloud のサービス側がリクエスト数の上限に到達し、それ以上の処理を受け付けられない状態です。

よくある原因

ループ処理でAPIを呼び出す間隔を設けていない

for ループや while ループの中で API を呼び出す際に、リクエスト間の待機時間(ウェイト)を設定していないと、数秒間に数千のリクエストが送信されます。GCP のクォータはプロジェクト単位で時間枠ごとに制限されているため、瞬間的な高頻度リクエストは即座にレート制限に引っかかります。

クォータが低いAPIを高頻度で実行している

Google Cloud のすべての API に等しいクォータが割り当てられているわけではありません。例えば Cloud Vision API や Cloud Translation API は、デフォルトのクォータが比較的低く設定されています。これらのAPI を大量のデータに対して実行すると、数分でクォータを消費し切ってしまいます。

複数のサービスが同じプロジェクトのクォータを共有して消費している

1つのプロジェクト内で複数のマイクロサービスやバッチ処理ジョブが並行して同じ API を呼び出している場合、クォータは各サービスで共有されます。一つのサービスが高頻度でリクエストを送ると、他のサービスのリクエストが拒否される可能性があります。

解決手順

1. Google Cloud Console でクォータを確認する

まずどのAPIのクォータに到達したかを特定します。

  1. Google Cloud Console(https://console.cloud.google.com)にアクセスします
  2. 左側のメニューから「IAMと管理」→「クォータと上限」を選択します
  3. 該当するサービス(例:Cloud Vision API、Compute Engine API)を検索します
  4. 「現在の利用状況」列でクォータの消費状況を確認します
  5. 上限に近い数値が表示されている API が 429 エラーの原因です

2. リトライ処理に指数バックオフを実装する

短期的な対策として、クライアント側でリトライロジックを追加します。429 エラーが返された時に、指数的に待機時間を増やしながら再試行します。

import time
from google.api_core.gapic_v1 import client_info
from google.cloud import vision
import google.api_core.exceptions

def call_api_with_backoff(func, max_retries=5):
    """指数バックオフ付きのAPIリトライ関数"""
    retry_count = 0
    wait_time = 1  # 初回の待機時間は1秒
    
    while retry_count < max_retries:
        try:
            return func()
        except google.api_core.exceptions.TooManyRequests:
            # 429 エラーをキャッチ
            if retry_count >= max_retries - 1:
                raise
            print(f"レート制限に達しました。{wait_time}秒待機します...")
            time.sleep(wait_time)
            wait_time *= 2  # 次回の待機時間を2倍にする
            retry_count += 1

# 使用例
client = vision.ImageAnnotatorClient()

def analyze_image():
    # APIの呼び出し処理
    return client.batch_annotate_images(requests)

result = call_api_with_backoff(analyze_image)

または Python の tenacity ライブラリを使用することもできます。

from tenacity import retry, stop_after_attempt, wait_exponential
import google.api_core.exceptions

@retry(
    stop=stop_after_attempt(5),
    wait=wait_exponential(multiplier=1, min=1, max=10),
    reraise=True
)
def call_api():
    # API呼び出し処理
    return client.some_api_call()

ループ処理内にも遅延を挿入します。

import time

items = range(1000)
for item in items:
    # APIを呼び出す処理
    result = client.process(item)
    time.sleep(0.1)  # 各リクエスト後に100ms待機

3. クォータの引き上げを申請する

恒久的な対策として、Google Cloud Console からクォータの引き上げをリクエストします。

  1. IAMと管理」→「クォータと上限」を開きます
  2. 制限に達している API をチェックボックスで選択します
  3. 画面上部の「クォータを編集」をクリックします
  4. 新しい上限値を入力します(例:1000→5000リクエスト/分)
  5. 「次へ」をクリックし、使用ケースを説明するコメントを入力します
  6. 「申請を送信」をクリックします

Google 側の審査には数時間~数日かかる場合があります。申請時に詳細な理由を記載するほど、承認される可能性が高まります。

それでも解決しない場合

クォータ引き上げが承認されるまでの間、リクエスト数を制御する以下の方法を検討します。

  • Cloud Tasks を使用して、リクエストを時間をかけてキューイングし、一度に送信する数を制限します
  • Cloud Pub/Sub でメッセージをバッファリングし、サブスクライバー側でレート制限を実装します
  • gRPC のクライアント側フロー制御(flow control)を設定し、同時リクエスト数を制限します

問題が解決しない場合は、Google Cloud サポート(有償プランが必要)に詳細なログを共有し、プロジェクト固有のボトルネックについて相談することを推奨します。


免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。