AWS Bedrock ThrottlingException na InvokeModel: diagnostyka limitów i naprawa błędów 429
Rozwiązanie błędów ThrottlingException i ModelStreamErrorException w Bedrock poprzez diagnostykę limitów, implementację backoff i zwiększenie kwot.
InvokeModel kończą z błędem ThrottlingException (HTTP 429)? Twoje konto przekroczyło limit tokenów na minutę lub zapytań na minutę. Rozwiązanie wymaga zdiagnozowania, który limit został osiągnięty, wdrożenia exponential backoff i złożenia wniosku o zwiększenie quoty.
Objawy
Logi aplikacji pokazują błędy API Bedrock:
botocore.exceptions.ClientError: An error occurred (ThrottlingException) when calling the InvokeModel operation: Too many requests, please wait before trying again.
Lub przy streamingu:
botocore.exceptions.EventStreamError: An error occurred (ModelStreamErrorException) when calling the InvokeModelWithResponseStream operation: Rate exceeded
Obserwowalny wpływ:
- Opóźnienie inferencji skacze z normalnych 200-400ms do timeoutów.
- Metryka
Bedrock > InvocationThrottlesw CloudWatch skacze z 0 do setek ms. - Użytkownicy końcowi widzą błędy lub długie ładowanie
- Ponawianie w aplikacji bez backoff pogarsza sytuację (efekt stada)
Przyczyna
AWS Bedrock stosuje limity per model, per region w dwóch wymiarach:
- Requests per minute (RPM) - liczba wywołań API na minutę, niezależnie od rozmiaru
- Tokens per minute (TPM) - suma tokenów wejściowych i wyjściowych przetworzonych na minutę
Domyślne limity różnią się w zależności od modelu. Przykładowe wartości (eu-central-1):
| Model | Domyślny RPM | Domyślny TPM |
|---|---|---|
| Claude Sonnet 4.6 | 60 | 80 000 |
| Claude 3.5 Haiku | 100 | 100 000 |
| Llama 3 70B | 60 | 100 000 |
Typowe przyczyny:
- Skok przetwarzania wsadowego - pipeline ingestion wywołuje Bedrock do embeddingów/klasyfikacji równocześnie
- Brak backoff - aplikacja natychmiast ponawia próby po błędzie, tworząc efekt stada (thundering herd)
- Współdzielona kwota - wiele środowisk (dev, staging, produkcja) korzysta z tego samego konta i regionu
- Długie prompty - kilka requestów z kontekstem 100K+ tokenów wyczerpuje cały budżet TPM
Rozwiązanie
Krok 1: Zidentyfikuj, który limit został osiągnięty
Sprawdź metryki CloudWatch w przestrzeni nazw Bedrock:
# Sprawdź liczbę throttle w ostatniej godzinie
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name InvocationThrottles \
--dimensions Name=ModelId,Value=anthropic.claude-3-5-haiku-20241022-v1:0 \
--start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 \
--statistics Sum \
--region eu-central-1
Sprawdź aktualne kwoty:
# Lista limitów usługi Bedrock
aws service-quotas list-service-quotas \
--service-code bedrock \
--region eu-central-1 \
--query 'Quotas[?contains(QuotaName, `InvokeModel`)].{Name:QuotaName, Value:Value}'
Krok 2: Zaimplementuj exponential backoff z jitter
Jeśli aplikacja ponawia natychmiast, pogarsza throttling. Dodaj prawidłowy backoff:
import time
import random
import boto3
from botocore.exceptions import ClientError
bedrock = boto3.client("bedrock-runtime", region_name="eu-central-1")
def invoke_with_backoff(model_id, body, max_retries=5):
"""Call Bedrock with exponential backoff and jitter."""
for attempt in range(max_retries):
try:
return bedrock.invoke_model(modelId=model_id, body=body)
except ClientError as e:
if e.response["Error"]["Code"] == "ThrottlingException":
if attempt == max_retries - 1:
raise
# Exponential backoff: 1s, 2s, 4s, 8s, 16s + jitter
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
else:
raise
Krok 3: Złóż wniosek o zwiększenie limitów
# Wniosek o zwiększenie RPM dla Claude 3.5 Haiku
aws service-quotas request-service-quota-increase \
--service-code bedrock \
--quota-code L-XXXXXXXX \
--desired-value 300 \
--region eu-central-1
Znajdź prawidłowy quota-code:
aws service-quotas list-service-quotas --service-code bedrock --region eu-central-1 \
--query 'Quotas[?contains(QuotaName, `Haiku`)].{Code:QuotaCode, Name:QuotaName, Value:Value}'
Zwiększenie limitów zajmuje zwykle 1-3 dni roboczych. W pilnych przypadkach otwórz zgłoszenie w AWS Support.
Krok 4: Zaprojektuj architekturę pod stałą przepustowość
Dla systemów produkcyjnych wymagających gwarantowanej przepustowości:
- Provisioned Throughput - wykupienie dedykowanych jednostek modelu zapewnia stały RPM/TPM bez throttlingu
- Routing multi-region - rozłożenie requestów między eu-central-1 i eu-west-1 (każdy region ma niezależne limity)
- Kolejkowanie requestów - użycie SQS do buforowania i przetwarzania ze stałą szybkością poniżej limitu
- Separacja kont - izolacja produkcji od dev/staging zapobiega rywalizacji o limity
Walidacja
Po wdrożeniu poprawek potwierdź, że throttling ustał:
# Zweryfikuj zero throttle w ostatnich 30 minutach
aws cloudwatch get-metric-statistics \
--namespace AWS/Bedrock \
--metric-name InvocationThrottles \
--dimensions Name=ModelId,Value=anthropic.claude-3-5-haiku-20241022-v1:0 \
--start-time $(date -u -v-30M +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 \
--statistics Sum \
--region eu-central-1
Oczekiwany wynik: Sum: 0.0 dla wszystkich punktów danych.
Ustaw alarm, żeby wyłapać przyszły throttling wcześnie:
aws cloudwatch put-metric-alarm \
--alarm-name bedrock-throttling-alert \
--metric-name InvocationThrottles \
--namespace AWS/Bedrock \
--statistic Sum \
--period 300 \
--threshold 10 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:eu-central-1:ACCOUNT:ops-alerts
Powiązane
- Uruchamianie LLM na AWS: Bedrock vs SageMaker vs self-hosting na EKS - porównanie architektur i kiedy wyjść poza Bedrock
- Dokumentacja limitów usługi AWS Bedrock