Ponowienia z wykładniczym wycofaniem
Używaj tenacity do ponawiania operacji po przejściowych błędach, stosując wykładniczo rosnące opóźnienia i jitter.
Ponowienia z wykładniczym wycofaniem to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.
Dlaczego ponawiać próby
Wywołania zewnętrzne (LLM, interfejsy API wyszukiwarek, wektorowe bazy danych) czasami przejściowo zawodzą. Proste ponowienie próby pozwala odzyskać sprawność po większości sporadycznych awarii bez niepokojenia użytkownika.
Czego NIE robić
Nie należy natychmiast ponawiać prób w ciasnej pętli — spowoduje to przeciążenie usługi, a ogranicznik liczby żądań zablokuje dostęp:
# BAD
for _ in range(10):
try:
return call_api()
except Exception:
passWykładnicze zwiększanie opóźnienia
Po każdym błędzie należy czekać dłużej. Wykładnik równy 2 jest przyjętą konwencją:
import time
def call_with_backoff(fn, attempts=5):
for i in range(attempts):
try:
return fn()
except TransientError:
if i == attempts - 1:
raise
time.sleep(2 ** i) # 1, 2, 4, 8, 16 secondsDodawanie jittera
Bez jittera ponowienia prób z wielu klientów synchronizują się, tworząc ruch typu thundering herd. Należy dodać losowe przesunięcie:
import random
sleep = (2 ** i) + random.uniform(0, 1)
time.sleep(sleep)Używanie biblioteki tenacity
Biblioteka tenacity implementuje to za Państwa:
from tenacity import retry, wait_exponential_jitter, stop_after_attempt, retry_if_exception_type
import requests
@retry(
wait=wait_exponential_jitter(initial=1, max=30),
stop=stop_after_attempt(5),
retry=retry_if_exception_type((requests.Timeout, requests.ConnectionError))
)
def search(query):
return requests.get('https://api.tavily.com/search', timeout=10).json()Ponawianie tylko prób po błędach przejściowych
Nie należy ponawiać prób w przypadku:
- błędów 4xx (nieprawidłowe żądanie — ponowienie próby nie pomoże)
- błędów uwierzytelniania
- błędów walidacji
Należy ponawiać próby w przypadku:
- przekroczenia limitu czasu
- błędów serwera 5xx
- limitów liczby żądań (z dłuższym czasem oczekiwania)
Ponawianie prób z uwzględnieniem limitu liczby żądań
Należy respektować nagłówek Retry-After:
if response.status_code == 429:
wait = int(response.headers.get('Retry-After', 5))
time.sleep(wait)
continueOgraniczanie łącznego czasu ponawiania prób
Należy ograniczyć łączny czas trwania ponawianych prób — zwykle do 30–60 sekund w przypadku wywołania obsługującego użytkownika:
from tenacity import stop_after_delay
@retry(
wait=wait_exponential_jitter(initial=1, max=10),
stop=stop_after_delay(60)
)
def call_api():
...Nagłówki idempotencji
W przypadku nieidempotentnych interfejsów API (np. Stripe) należy dołączać klucz idempotencji przy każdym ponowieniu próby, aby eliminować duplikaty:
headers = {'Idempotency-Key': f'agent-call-{run_id}-{tool_id}'}Ponawianie również wywołania LLM
SDK OpenAI i Anthropic automatycznie ponawiają próbę 1–2 razy. Można to skonfigurować:
client = OpenAI(max_retries=5, timeout=30.0)Ponawianie prób w kodzie asynchronicznym
W przypadku kodu asynchronicznego:
from tenacity import AsyncRetrying
async for attempt in AsyncRetrying(wait=wait_exponential_jitter(), stop=stop_after_attempt(5)):
with attempt:
result = await call_api()Logowanie ponawianych prób
Każde ponowienie próby powinno rejestrować: numer próby, czas uśpienia i przyczynę błędu. W przeciwnym razie debugowanie problemu „dlaczego to trwa tak długo?” jest niemożliwe.
Ponawianie prób a limity czasu
Należy ustawić krótki limit czasu dla każdej próby (np. 10 s) oraz łączny limit za pomocą stop_after_delay (np. 60 s). Bez obu tych ograniczeń zawieszone połączenie może trwać w nieskończoność.
Dlaczego jitter
Dlaczego należy dodawać losowy jitter do opóźnień między ponowieniami prób?
Podsumowanie
Wykładnicze zwiększanie opóźnienia + jitter + ograniczony łączny czas + ponawianie tylko po błędach przejściowych. Należy używać biblioteki tenacity, aby uniknąć powtarzalnego kodu.
Często zadawane pytania
Czy lekcja „Ponowienia z wykładniczym wycofaniem” jest bezpłatna?
Tak — pełny tekst „Ponowienia z wykładniczym wycofaniem” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.
Co nauczysz się w „Ponowienia z wykładniczym wycofaniem”?
Używaj tenacity do ponawiania operacji po przejściowych błędach, stosując wykładniczo rosnące opóźnienia i jitter. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Agents?
Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Ponowienia z wykładniczym wycofaniem”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?
Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Idempotentne narzędzia i efekty uboczne
- Ponowienia z wykładniczym wycofaniem
- Limity czasu i circuit breaker
- Walidowanie danych wyjściowych narzędzi (Pydantic)