Hız Sınırlama ve Yeniden Deneme Mantığı
Üstel bekleme, 429 işleme ve API'leri ölçülü kullanma.
Hız Sınırlama ve Yeniden Deneme Mantığı, CoddyKit'te ücretsiz bir AI Agents dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Agents öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Agents kursu toplamda 4 dersten oluşur.
Hız Sınırlaması Nedir?
Hız sınırlaması, API'lerin aşırı yüklenmeye karşı kendilerini koruma yöntemidir. Aracınız çok kısa sürede çok fazla istek gönderdiğinde API, 429 Too Many Requests döndürür. Yaygın sınırlar arasında saniye, dakika veya gün başına istek sayısı bulunur.
Hız sınırlarını yok saymak, aracıların engellenmesine, API anahtarlarının iptal edilmesine ve ek ücretlere yol açar.
import requests
response = requests.get(
'https://api.example.com/data',
headers={'Authorization': 'Bearer YOUR_KEY'}
)
if response.status_code == 429:
print('Rate limit exceeded!')
# Check headers for limit details
limit = response.headers.get('X-RateLimit-Limit')
remaining = response.headers.get('X-RateLimit-Remaining')
reset = response.headers.get('X-RateLimit-Reset')
print(f'Limit: {limit}, Remaining: {remaining}, Reset: {reset}')Retry-After Üstbilgisi
Bir API 429 döndürdüğünde, yeniden denemeden önce tam olarak kaç saniye beklemeniz gerektiğini belirten bir Retry-After üstbilgisi çoğu zaman yanıta eklenir. Bu üstbilgiye her zaman uyun; onu yok sayıp hemen yeniden denemek yalnızca başka bir 429 almanıza neden olur.
import requests
import time
def request_with_retry_after(url, headers):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f'Rate limited. Waiting {retry_after} seconds...')
time.sleep(retry_after)
# Retry once after waiting
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()Üstel Geri Çekilme
Üstel geri çekilme, standart yeniden deneme stratejisidir: her başarısız denemeden sonra daha uzun süre beklenir. Birinci denemede 2 saniye, ikinci denemede 4 saniye, üçüncü denemede 8 saniye beklenmesi gibi devam eder. Bu, sunucu üzerindeki yükü kademeli olarak azaltır ve sunucuya toparlanması için zaman tanır.
Formül: wait = 2 ** attempt
import requests
import time
def get_with_exponential_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers, timeout=(5, 30))
if response.status_code == 200:
return response.json()
if response.status_code in (429, 500, 502, 503):
wait = 2 ** attempt # 1, 2, 4, 8, 16 seconds
print(f'Attempt {attempt+1} failed ({response.status_code}). '
f'Waiting {wait}s before retry...')
time.sleep(wait)
else:
response.raise_for_status() # non-retryable error
raise Exception(f'Failed after {max_retries} retries')Geri Çekilmeye Rastgelelik Ekleme
Birçok aracı aynı anda yeniden denerse (kısa süreli bir kesintinin ardından sık görülen bir durum), hepsi aynı anda uyanır ve hemen yeniden hız sınırına takılan aynı anda hücum eden bir kalabalık oluşturur. Rastgele gecikme eklemek, yeniden denemeleri zamana yayarak sunucu yükünü azaltır.
import requests
import time
import random
def get_with_jittered_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers, timeout=(5, 30))
if response.status_code == 200:
return response.json()
if response.status_code in (429, 500, 502, 503):
base_wait = 2 ** attempt
# Add random jitter: actual wait is 50%-100% of base
jitter = random.uniform(0.5, 1.0)
wait = base_wait * jitter
print(f'Waiting {wait:.1f}s (attempt {attempt+1})')
time.sleep(wait)
else:
response.raise_for_status()
raise Exception(f'Failed after {max_retries} retries')tenacity Kitaplığı
tenacity, yeniden deneme mantığı için en popüler Python kitaplığıdır. Üstel geri çekilmeyi, rastgele gecikmeyi, maksimum yeniden deneme sayısını ve özel durdurma koşullarını temiz bir dekoratör sözdizimiyle yönetir. Elle yazılmış yeniden deneme döngülerinden çok daha güvenilirdir.
from tenacity import (
retry, stop_after_attempt, wait_exponential,
retry_if_exception_type, before_sleep_log
)
import requests
import logging
logger = logging.getLogger(__name__)
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=2, max=60),
retry=retry_if_exception_type(requests.exceptions.HTTPError),
before_sleep=before_sleep_log(logger, logging.WARNING)
)
def fetch_data(url, headers):
response = requests.get(url, headers=headers, timeout=(5, 30))
if response.status_code == 429:
response.raise_for_status() # triggers retry
response.raise_for_status()
return response.json()Özel Yeniden Deneme Koşuluyla tenacity
tenacity'ye yalnızca belirli durum kodlarında (429 ve 5xx gibi) yeniden deneme yapmasını, yeniden denemeden yararlanamayacak istemci hatalarında (4xx) ise hemen durmasını öğretebilirsiniz. Yanıtı incelemek için retry_if_result veya özel bir çağrılabilir nesne kullanın.
from tenacity import (
retry, stop_after_attempt, wait_exponential,
retry_if_result
)
import requests
def is_retryable_response(response):
return response.status_code in (429, 500, 502, 503, 504)
@retry(
stop=stop_after_attempt(4),
wait=wait_exponential(multiplier=2, min=2, max=30),
retry=retry_if_result(is_retryable_response)
)
def resilient_get(url, headers):
response = requests.get(url, headers=headers, timeout=(5, 30))
return response # retry logic inspects the response object
# Usage
response = resilient_get(
'https://api.example.com/data',
{'Authorization': 'Bearer YOUR_KEY'}
)
data = response.json()Hız Sınırlarını Proaktif Yönetme
En iyi strateji, en başta hız sınırlarına takılmaktan kaçınmaktır. Her yanıttaki hız sınırı üstbilgilerini kontrol edin ve sınıra yaklaştığınızda yavaşlayın. Birçok API, X-RateLimit-Remaining ve X-RateLimit-Reset üstbilgilerini içerir.
import requests
import time
class RateLimitAwareClient:
def __init__(self, base_url, api_key):
self.base_url = base_url
self.headers = {'Authorization': f'Bearer {api_key}'}
self.remaining = 1000 # assume generous limit
def get(self, path):
# Proactively slow down if nearly exhausted
if self.remaining < 10:
print('Rate limit nearly exhausted, sleeping 5s...')
time.sleep(5)
response = requests.get(
f'{self.base_url}{path}', headers=self.headers
)
# Update remaining from response headers
remaining_str = response.headers.get('X-RateLimit-Remaining')
if remaining_str:
self.remaining = int(remaining_str)
response.raise_for_status()
return response.json()Maksimum Yeniden Deneme Sayısı ve Vazgeçme
Yeniden deneme mantığının mutlaka bir sınırı olmalıdır. Sonsuza kadar yeniden denemek, tüm aracılarınızın yeniden deneme döngülerinde takılı kaldığı zincirleme hatalara yol açabilir. max_retries sayısına ulaştıktan sonra neyin başarısız olduğuna ilişkin bağlamı içeren son bir istisna oluşturun; böylece aracı bunu günlüğe kaydedip diğer işlere geçebilir.
import requests
import time
class MaxRetriesExceeded(Exception):
def __init__(self, url, attempts, last_status):
self.url = url
self.attempts = attempts
self.last_status = last_status
super().__init__(
f'Failed {url} after {attempts} attempts '
f'(last status: {last_status})'
)
def fetch_with_limit(url, headers, max_retries=3):
last_response = None
for attempt in range(max_retries):
last_response = requests.get(url, headers=headers)
if last_response.status_code == 200:
return last_response.json()
time.sleep(2 ** attempt)
raise MaxRetriesExceeded(url, max_retries, last_response.status_code)Devre Kesici Deseni
Devre kesici deseni, aracınızın başarısız olan bir hizmeti sürekli zorlamasını önler. Belirli bir hata eşiğine ulaşıldıktan sonra devre "açılır" ve tüm istekler ağa ulaşmadan hemen başarısız olur. Bekleme süresinin ardından devre bir istek dener; istek başarılı olursa devre kapanır ve normal çalışma devam eder.
import time
class CircuitBreaker:
CLOSED, OPEN, HALF_OPEN = 'closed', 'open', 'half_open'
def __init__(self, failure_threshold=5, recovery_timeout=60):
self.state = self.CLOSED
self.failures = 0
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.opened_at = None
def call(self, func, *args, **kwargs):
if self.state == self.OPEN:
if time.time() - self.opened_at > self.recovery_timeout:
self.state = self.HALF_OPEN
else:
raise Exception('Circuit OPEN — service unavailable')
try:
result = func(*args, **kwargs)
self.failures = 0
self.state = self.CLOSED
return result
except Exception as e:
self.failures += 1
if self.failures >= self.failure_threshold:
self.state = self.OPEN
self.opened_at = time.time()
print(f'Circuit OPENED after {self.failures} failures')
raise
# --- demo ---
def flaky():
raise ValueError('upstream 500')
def works():
return 'ok'
cb = CircuitBreaker(failure_threshold=3, recovery_timeout=60)
for i in range(3):
try:
cb.call(flaky)
except Exception as e:
print(f'call {i+1} failed: {e}')
print(f'Breaker state after 3 failures: {cb.state}')
try:
cb.call(flaky)
except Exception as e:
print(f'Rejected without calling flaky(): {e}')
Sınırlar İçinde Kalmak İçin İstekleri Kuyruğa Alma
Toplu işlem halinde çok sayıda çağrı yapan aracılar için, sınırlar içinde kalmak amacıyla belirteç kovası veya uyku tabanlı basit bir hız sınırlayıcı kullanın. API'nin hız sınırına göre çağrılar arasındaki güvenli aralığı hesaplayın (örneğin dakikada 60 çağrı = saniyede 1 çağrı).
import requests
import time
def batch_requests(urls, headers, calls_per_minute=60):
interval = 60.0 / calls_per_minute # seconds between calls
results = []
for i, url in enumerate(urls):
start = time.time()
response = requests.get(url, headers=headers, timeout=(5, 30))
response.raise_for_status()
results.append(response.json())
print(f'Processed {i+1}/{len(urls)}')
# Sleep for remaining time in the interval
elapsed = time.time() - start
sleep_time = interval - elapsed
if sleep_time > 0:
time.sleep(sleep_time)
return resultsYeniden Deneme Mantığını Geri Çekilme Üstbilgileriyle Birleştirme
En dayanıklı desen, sunucunun belirlediği bekleme sürelerini (Retry-After) yedek seçenek olarak üstel geri çekilmeyle birleştirir. Sunucunun yönlendirmesi mevcut olduğunda her zaman onu tercih edin; yeniden ne zaman deneyebileceğinizi tam olarak sunucu bilir.
import requests
import time
import random
def smart_retry(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers, timeout=(5, 30))
if response.status_code == 200:
return response.json()
if response.status_code == 429:
# Use Retry-After if provided, else exponential backoff
retry_after = response.headers.get('Retry-After')
if retry_after:
wait = int(retry_after)
else:
wait = (2 ** attempt) + random.uniform(0, 1)
print(f'429 rate limit. Waiting {wait:.1f}s...')
time.sleep(wait)
elif response.status_code >= 500:
wait = (2 ** attempt) + random.uniform(0, 1)
print(f'Server error {response.status_code}. Waiting {wait:.1f}s...')
time.sleep(wait)
else:
response.raise_for_status() # non-retryable
raise Exception(f'Gave up after {max_retries} attempts')Kısa Kontrol: Üstel Geri Çekilme
Yeniden deneme stratejileri konusundaki anlayışınızı sınayın.
Hız Sınırlaması ve Yeniden Deneme Özeti
Aracılarınız artık hız sınırlarını sorunsuz şekilde yönetebilir:
- 429 Çok Fazla İstek —
Retry-Afterüstbilgisine uyun; yeniden denemeden önce bekleyin - Üstel geri çekilme —
wait = 2^attempther yeniden denemede bekleme süresini iki katına çıkarır - Rastgele gecikme — birden çok aracı örneğindeki yeniden denemeleri zamana yaymak için rastgelelik ekler
- tenacity — tüm yeniden deneme mantığını dekoratörler ve temiz yapılandırmayla yönetir
- Devre kesici — belirli bir eşiğe ulaşıldığında başarısız bir hizmeti zorlamayı durdurur
- Proaktif hız sınırlama —
X-RateLimit-Remainingdeğerini kontrol eder ve sınıra ulaşmadan önce yavaşlar
Sıkça Sorulan Sorular
“Hız Sınırlama ve Yeniden Deneme Mantığı” dersi ücretsiz mi?
Evet — “Hız Sınırlama ve Yeniden Deneme Mantığı” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Agents kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Agents kursu toplamda 4 dersten oluşur.
“Hız Sınırlama ve Yeniden Deneme Mantığı” dersinde ne öğreneceğim?
Üstel bekleme, 429 işleme ve API'leri ölçülü kullanma. AI Agents ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
AI Agents öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te AI Agents, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Hız Sınırlama ve Yeniden Deneme Mantığı” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu AI Agents dersinde kod yazıp çalıştırabilir miyim?
Evet. Her AI Agents dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Aracı Geliştiricileri İçin REST API Temelleri
- Kimlik Doğrulama: API Anahtarları ve OAuth
- API Yanıtlarını ve Hatalarını Ele Alma
- Hız Sınırlama ve Yeniden Deneme Mantığı