Dijital pazarlama dünyasından güncel bilgiler için blog bölümününüzü ziyaret ettiniz mi?

Yapay zeka devriminin merkezinde yer alan ChatGPT ve OpenAI API’leri, uygulamalarımıza daha önce hayal bile edemeyeceğimiz yetenekler katmamızı sağladı. Bir prototipten çalışan bir ürüne, oradan da binlerce kullanıcının aynı anda kullandığı bir platforma geçiş… Bu heyecan verici bir yolculuktur. Ancak tam da bu büyüme anında, geliştiricilerin karşısına soğuk bir duvar çıkar: Error 429: Too Many Concurrent Requests.

Bu hata, uygulamanızın başarılı olduğunun bir kanıtıdır. O kadar çok talep alıyorsunuz ki, OpenAI’nin size ayırdığı anlık kapasiteyi aşıyorsunuz. Ancak bu “başarı” bir anda kabusa dönüşebilir. Kullanıcılar hata mesajları alır, hizmetiniz kesintiye uğrar ve itibarınız zedelenir.

Peki, bu hata tam olarak ne anlama geliyor? Daha da önemlisi, onu sadece “düzeltmek” değil, aynı zamanda gelecekte bir daha karşınıza çıkmayacak şekilde nasıl kalıcı olarak çözebilirsiniz?

Bu 3000 kelimelik kapsamlı rehberde, “Too Many Concurrent Requests” hatasının anatomisini inceleyeceğiz. Basit bir time.sleep() komutundan, karmaşık ve ölçeklenebilir kuyruk (queue) mimarilerine kadar her seviyede çözümü masaya yatıracağız. Bu makale, sadece bir “hata ayıklama” rehberi değil, aynı zamanda API’lerle çalışan sistemlerinizi nasıl daha dayanıklı (resilient) ve ölçeklenebilir (scalable) hale getireceğinize dair bir mimari kılavuzdur.

İster küçük bir Python scripti yazan bir hobi geliştiricisi olun, ister binlerce anlık kullanıcıya hizmet veren bir SaaS uygulamasının baş mimarı olun, bu yazıda aradığınız çözümü bulacaksınız.

Hazırsanız, başlayalım.

Bölüm 1: Hatayı Anlamak: “Concurrent” Neden “Rate Limit” Değildir?

Çoğu geliştirici, “Too Many Concurrent Requests” hatasını gördüğünde, bunu tipik “Rate Limit Exceeded” (RPM/TPM) hatasıyla karıştırır. Bu, yapılacak ilk ve en kritik hatadır. Sorunu çözmek için önce bu iki kavram arasındaki nüansı anlamalıyız.

Rate Limit (RPM/TPM) Nedir?

Rate limit (Oran Sınırı), belirli bir zaman diliminde (genellikle bir dakika) yapabileceğiniz toplam istek sayısını kısıtlar.

  • RPM (Requests Per Minute): Dakika başına gönderebileceğiniz maksimum istek sayısı. Örneğin, RPM’iniz 100 ise, bir dakika içinde 101. isteği gönderirseniz hata alırsınız.
  • TPM (Tokens Per Minute): Dakika başına işleyebileceğiniz maksimum token (kelime parçası) sayısı. Bu, özellikle maliyet ve işlem gücüyle ilgilidir.

Concurrency Limit (Eşzamanlılık Sınırı) Nedir?

Concurrency (Eşzamanlılık) sınırı ise, zaman diliminden bağımsız olarak, aynı anda OpenAI sunucularında aktif olarak işlenebilecek maksimum istek sayınızdır.

Mükemmel Analoji: Restoran Mutfağı

Bunu bir restoran mutfağı olarak düşünün:

  1. Rate Limit (RPM): Mutfağın bir saatte servis edebileceği toplam sipariş sayısıdır (örn. saatte 100 sipariş).
  2. Concurrency Limit (Eşzamanlılık): Mutfakta aynı anda çalışabilen aşçı sayısıdır (örn. 5 aşçı).

Günün sakin bir anında, saatte sadece 20 sipariş alabilirsiniz (RPM’in çok altında). Ancak bu 20 siparişin tümü aynı saniyede gelirse ve sizin sadece 5 aşçınız (concurrency limit) varsa, aşçılar meşgulken gelen 15 sipariş “Çok Meşgulüz, Lütfen Bekleyin” (Too Many Concurrent Requests) hatasını alır.

Mutfak (API) bir siparişi (isteği) bitirdiğinde, bekleyen siparişlerden birini alır. Sorun şu ki, siz siparişleri o kadar hızlı gönderiyorsunuz ki, aşçılar henüz işlerini bitiremeden yenileri yığılıyor.

Neden OpenAI Eşzamanlılığı Sınırlar?

Bu kısıtlama, hem OpenAI’nin altyapısını korumak hem de tüm kullanıcılara adil bir hizmet kalitesi (QoS – Quality of Service) sunmak için vardır.

  1. Altyapı Stabilitesi: GPU’lar pahalı ve sınırlı kaynaklardır. Sınırsız eşzamanlı istek, sunucuların çökmesine veya yanıt sürelerinin kabul edilemez düzeyde yavaşlamasına neden olur.
  2. Adil Kullanım: Bir kullanıcı tüm kaynakları domine ederse, diğer kullanıcılar hizmet alamaz. Bu limitler, kaynakların adil bir şekilde dağıtılmasını sağlar.
  3. Hizmet Öngörülebilirliği: Sınırlar, sistemin davranışını öngörülebilir kılar. OpenAI, belirli bir anda ne kadar yüke maruz kalacağını bilir ve buna göre kapasite planlaması yapabilir.

Bu hatayı alıyorsanız, sebebi dakikada çok fazla istek göndermeniz değil, aynı saniye içinde çok fazla istek göndermenizdir. Uygulamanızın mimarisi, büyük olasılıkla async (asenkron) programlama, threading (iş parçacıkları) veya paralel işleme (parallel processing) kullanarak çok fazla işi aynı anda yapmaya çalışmaktadır.

Bölüm 2: Teşhis: Sınırlarınızı Nerede Bulabilirsiniz?

Sorunu çözmeden önce, kişisel sınırlarınızın ne olduğunu bilmeniz gerekir. Bu sınırlar statik değildir; OpenAI hesabınızın “kullanım katmanına” (Usage Tier) göre değişir.

OpenAI Kullanım Katmanları (Usage Tiers)

OpenAI, API kullanımınızı ve ödeme geçmişinizi baz alarak sizi farklı katmanlara ayırır. Bu katmanlar, hem RPM/TPM hem de eşzamanlılık limitlerinizi doğrudan etkiler.

  • Tier 1 (Free / Yeni Hesaplar): Genellikle en düşük limitlere sahiptir. Örneğin, GPT-4o için 3 eşzamanlı istek gibi çok düşük bir limitle başlayabilirsiniz.
  • Tier 2 (Genellikle 5$’lık ödeme sonrası): Limitleriniz bir kademe artar.
  • Tier 3 (Genellikle 50$’lık ödeme sonrası): Limitler belirgin şekilde yükselir.
  • Tier 4 ve 5 (Yüksek hacimli ve kurumsal): Çok daha yüksek limitlere ve özel destek seçeneklerine sahip olursunuz.

Limitlerinizi Kontrol Etme

  1. OpenAI hesabınıza giriş yapın.
  2. Sol menüden “Settings” (Ayarlar) bölümüne gidin.
  3. “Limits” (Limitler) sekmesine tıklayın.

Burada, kullandığınız her model (GPT-4o, GPT-4 Turbo, vb.) için hem “Rate Limits” (RPM, TPM) hem de “Concurrency Limits” (Eşzamanlı İstek Sınırı) değerlerinizi net bir şekilde göreceksiniz.

Örnek bir senaryo:

Diyelim ki “Tier 2” bir hesaptasınız ve GPT-4o için eşzamanlılık sınırınız 10. Bu, uygulamanızın OpenAI’ye aynı anda en fazla 10 istek gönderebileceği anlamına gelir. 11. isteği gönderdiğiniz anda, bu istek 429: Too Many Concurrent Requests hatası alacaktır.

Bu sayıyı bilmek, birazdan tartışacağımız mimari çözümler için (örneğin, kuyruk sistemindeki “worker” sayısı) kritik öneme sahiptir.

Bölüm 3: Hızlı Çözümler (Ama Tehlikeli Olanlar)

Hemen üretime geçmeniz gerekiyor ve bir kuyruk sistemi kuracak vaktiniz yok. Panik içinde hızlı bir çözüm arıyorsunuz. İşte acil durumlarda kullanılabilecek, ancak uzun vadede kaçınmanız gereken bazı “yamalar”.

1. Basit sleep() / delay() Kullanımı (Kötü Fikir)

En içgüdüsel tepki, her istek arasına basit bir bekleme süresi koymaktır.

Python (Kötü Örnek):

Python

import openai
import time

client = openai.OpenAI()
prompts = ["prompt 1", "prompt 2", ..., "prompt 100"]

for prompt in prompts:
    try:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": prompt}]
        )
        print(response.choices[0].message.content)
    except openai.RateLimitError as e:
        print(f"Hata: {e}. 10 saniye bekleniyor...")
        time.sleep(10) # <-- Hızlı ama kötü çözüm
    except Exception as e:
        print(f"Başka bir hata: {e}")
    
    # Her istek arasına körlemesine bekleme eklemek
    time.sleep(1) # <-- Daha da kötü

Neden Kötü?

  • Verimsizlik: API yanıtı 500 milisaniye sürse bile, siz 1 saniye (veya hata durumunda 10 saniye) bekliyorsunuz. Bu, toplam işlem süresini gereksiz yere uzatır.
  • Engelleme (Blocking): time.sleep() ana iş parçacığını (main thread) bloke eder. Eğer bu bir web sunucusuysa (örn. Flask veya Django), bu bekleme sırasında diğer kullanıcılara hizmet veremez hale gelir.
  • Ölçeklenmez: Limitiniz 10 ise ve 1000 isteğiniz varsa, bu işlem çok uzun sürecektir.

2. Kaba Hata Yakalama ve Yeniden Deneme

Hata aldığınızda rastgele bir süre bekleyip tekrar denemek.

Python

# ... (önceki kod) ...
    except openai.RateLimitError as e:
        print(f"Rate limit hatası: {e}. 5 saniye sonra yeniden denenecek.")
        time.sleep(5)
        # BURADA YENİDEN DENEME MANTIĞI EKSİK!
        # Genellikle bu, bir 'while True:' döngüsü içine alınır ki bu daha da tehlikelidir.

Bu yaklaşım, bir sonraki bölümde anlatacağımız “Exponential Backoff”un ilkel bir versiyonudur ve genellikle daha fazla soruna yol açar.

Bu “hızlı” çözümler, yangını geçici olarak söndürür ama temeldeki mimari sorunu çözmez. Uygulamanız büyüdükçe, bu yamalar yetersiz kalacak ve sisteminiz tekrar tekrar çökecektir.

Bölüm 4: Kalıcı Çözüm (1): Eksponansiyel Geri Çekilme (Exponential Backoff)

Sisteminizi dayanıklı (resilient) hale getirmenin ilk adımı, hataları akıllıca yönetmektir. “Exponential Backoff”, ağa bağlı sistemlerde bir standarttır.

Nedir?

Bir API isteği başarısız olduğunda (özellikle 429 veya 5xx gibi geçici hatalarda), hemen tekrar denemek yerine:

  1. Kısa bir süre (örn. 1 saniye) bekleyin ve tekrar deneyin.
  2. Yine mi başarısız oldu? Bekleme süresini katlayın (örn. 2 saniye) ve tekrar deneyin.
  3. Yine mi başarısız oldu? Tekrar katlayın (örn. 4 saniye, sonra 8 saniye…).
  4. Bu işlemi, önceden belirlenmiş maksimum deneme sayısına veya maksimum bekleme süresine ulaşana kadar tekrarlayın.

Neden İşe Yarar?

Bu strateji, API sunucusuna “nefes alması” için zaman tanır. Eğer sunucu geçici bir yük altındaysa, tüm istemcilerin aynı anda sleep(1) yapıp tekrar saldırması yerine, bu “katlanarak artan” bekleme süreleri, yeniden denemelerin zaman içinde dağılmasını sağlar (buna “jitter” eklemek daha da iyidir).

“Too Many Concurrent Requests” hatası için bu mükemmeldir. Çünkü bu, “şu an meşgulüm” demektir. 1 saniye sonra tekrar denediğinizde, diğer isteklerden biri bitmiş olabilir ve sizin isteğiniz için bir “slot” açılmış olabilir.

Python ile tenacity Kütüphanesi Kullanımı

Bunu manuel olarak yazmak yerine, tenacity gibi harika kütüphaneler kullanmak en iyisidir.

Önce kütüphaneyi kurun:

pip install tenacity openai

Şimdi, API çağrınızı bu kütüphane ile “sarmalayalım”:

Python

import openai
import time
from tenacity import (
    retry,
    stop_after_attempt,
    wait_random_exponential,
    retry_if_exception_type
)

client = openai.OpenAI()

# Bu 'decorator' (bezemci), alttaki fonksiyonu yeniden deneme mantığı ile donatır.
@retry(
    # Sadece 'RateLimitError' veya 'InternalServerError' gibi geçici hatalarda yeniden dene.
    # 'AuthenticationError' gibi kalıcı hatalarda deneme.
    retry=retry_if_exception_type((openai.RateLimitError, openai.InternalServerError)),
    
    # 'wait_random_exponential' en iyi stratejidir.
    # multiplier=1: 1s, 2s, 4s, 8s... diye artar.
    # max=60: Maksimum bekleme süresi 60 saniyeyi geçmez.
    wait=wait_random_exponential(multiplier=1, max=60),
    
    # Toplamda 5 kez denedikten sonra vazgeç ve hatayı yükselt.
    stop=stop_after_attempt(5)
)
def chat_completion_with_backoff(model, messages):
    """
    OpenAI'ye eksponansiyel geri çekilme ile istek gönderen
    dayanıklı bir fonksiyon.
    """
    print("API'ye istek gönderiliyor...")
    response = client.chat.completions.create(
        model=model,
        messages=messages
    )
    return response

# --- Kullanım ---
prompts = ["prompt 1", "prompt 2", "prompt 3"]
for prompt in prompts:
    try:
        messages = [{"role": "user", "content": prompt}]
        response = chat_completion_with_backoff(model="gpt-4o", messages=messages)
        print(f"Cevap: {response.choices[0].message.content}\n")
    except Exception as e:
        # 5 denemeden sonra hala başarısız olursa, burada yakalanır.
        print(f"'{prompt}' için API çağrısı kalıcı olarak başarısız oldu: {e}")

Bu kod, RateLimitError aldığında (ki “Too Many Concurrent Requests” bu kategoriye girer) otomatik olarak bekleyip tekrar deneyecektir.

Ancak, bu çözüm de tek başına yeterli değildir. Neden?

Çünkü elinizde 1000 istek varsa ve eşzamanlılık sınırınız 10 ise, bu 1000 isteği paralel olarak göndermeye çalıştığınızda, ilk 10’u geçer, kalan 990’ı RateLimitError alır ve hepsi aynı anda exponential backoff döngüsüne girer. Bu, bir kaosa ve “yeniden deneme fırtınasına” (retry storm) yol açabilir.

Exponential backoff, sisteminizi dayanıklı yapar, ancak eşzamanlılık sorununu temelden çözmez. Bunun için bir sonraki adıma ihtiyacımız var.

Bölüm 5: Kalıcı Çözüm (2): Semafor (Semaphore) ile Eşzamanlılığı Sınırlandırma

“Too Many Concurrent Requests” hatasının tanımı neydi? Aynı anda çok fazla istek göndermek.

Çözüm nedir? Aynı anda göndereceğimiz istek sayısını bilinçli olarak kısıtlamak.

Bunun için programlamada kullanılan klasik bir konsept vardır: Semaphore (Semafor).

Bir semafor, belirli bir sayıda “izne” (permit) sahip bir sayaç gibidir. İşlem yapmak isteyen her iş parçacığı (thread) veya asenkron görev (task), önce semafordan bir izin istemek zorundadır.

  • Eğer izin varsa (sayaç > 0), semafor bir izin verir (sayacı 1 azaltır) ve görevin çalışmasına izin verir.
  • Eğer izin yoksa (sayaç = 0), semafor görevi, bir izin serbest kalana kadar bekletir.
  • Görev işini bitirdiğinde, izni semafora geri verir (sayacı 1 artırır), böylece bekleyen başka bir görev başlayabilir.

Bu, bizim senaryomuz için mükemmeldir! OpenAI API limitlerimizde “Concurrency Limit” 10 mu yazıyor? O zaman biz de kodumuzda değeri 10 olan bir semafor tanımlarız.

Böylece, uygulamamız 1000 isteği aynı anda göndermeye çalışsa bile, semaforumuz ilk 10’a izin verecek, 11. isteği (ve sonrasını) 10 görevden biri bitene kadar nazikçe bekletecektir.

Bu, bir hata alıp sonra düzeltmek (reaktif) yerine, hatayı hiç almamayı (proaktif) sağlayan çok daha zarif bir çözümdür.

Python asyncio.Semaphore ile Uygulama

Modern Python’da bu iş için asyncio (asenkron G/Ç) kütüphanesi idealdir. Web sunucuları ve yoğun G/Ç işlemleri için tasarlanmıştır.

pip install asyncio openai

Python

import asyncio
import openai
import time
from tenacity import (
    retry,
    stop_after_attempt,
    wait_random_exponential,
    retry_if_exception_type
)

# --- OpenAI İstemcisi ---
# Asenkron kullanım için 'AsyncOpenAI' kullanmalıyız
client = openai.AsyncOpenAI()

# --- Tenacity ile Güçlendirilmiş API Çağrısı ---
# (Bir önceki bölümdeki @retry decorator'ü burada da kullanmak
# sistemimizi ÇOK daha dayanıklı hale getirir. Hem semafor hem backoff!)

@retry(
    retry=retry_if_exception_type((openai.RateLimitError, openai.InternalServerError)),
    wait=wait_random_exponential(multiplier=1, max=60),
    stop=stop_after_attempt(5)
)
async def protected_chat_completion(model, messages, task_id):
    """
    Semafor tarafından korunacak ve hata durumunda yeniden deneyecek
    asenkron API çağrısı.
    """
    print(f"[Task {task_id}] İstek gönderiliyor...")
    start_time = time.time()
    
    response = await client.chat.completions.create(
        model=model,
        messages=messages
    )
    
    end_time = time.time()
    print(f"[Task {task_id}] Cevap alındı. Süre: {end_time - start_time:.2f}s")
    return response.choices[0].message.content

# --- Ana İşleyici Fonksiyon ---
async def process_batch_with_semaphore(prompts, concurrency_limit):
    """
    Tüm prompt'ları bir semafor ile kontrollü bir şekilde işler.
    """
    
    # Semaforumuzu API limitimize göre ayarlıyoruz.
    # Örneğin, Tier 2 için 10.
    semaphore = asyncio.Semaphore(concurrency_limit)
    
    tasks = [] # Görevleri tutacağımız liste

    async def run_task_with_semaphore(prompt, task_id):
        # 'async with semaphore:' bloğu
        # Bu bloğa girmeden önce semafordan bir izin alınmasını bekler.
        # Bloktan çıkıldığında izni otomatik olarak geri verir.
        async with semaphore:
            print(f"[Task {task_id}] İzin alındı, işleme başlıyor.")
            try:
                result = await protected_chat_completion(
                    model="gpt-4o",
                    messages=[{"role": "user", "content": prompt}],
                    task_id=task_id
                )
                return (task_id, "Başarılı", result)
            except Exception as e:
                print(f"[Task {task_id}] Görev kalıcı olarak başarısız oldu: {e}")
                return (task_id, "Başarısız", str(e))

    # Tüm görevleri oluştur
    for i, prompt in enumerate(prompts):
        tasks.append(run_task_with_semaphore(prompt, i + 1))
    
    # Görevleri çalıştır ve sonuçları topla
    # asyncio.gather tüm görevleri "aynı anda" başlatır,
    # ancak semaforumuz sayesinde sadece 'concurrency_limit' kadarı
    # aynı anda API'ye istek gönderebilir.
    results = await asyncio.gather(*tasks)
    
    return results

# --- Çalıştırma ---
async def main():
    # 50 adet sahte prompt oluşturalım
    all_prompts = [f"Bana {i} sayısı hakkında ilginç bir bilgi ver." for i in range(1, 51)]
    
    # OpenAI API Limitimizin 10 olduğunu varsayalım
    API_CONCURRENCY_LIMIT = 10
    
    print(f"Toplam {len(all_prompts)} istek işlenecek.")
    print(f"Eşzamanlılık Sınırı: {API_CONCURRENCY_LIMIT}\n")
    
    start_total_time = time.time()
    
    results = await process_batch_with_semaphore(all_prompts, API_CONCURRENCY_LIMIT)
    
    end_total_time = time.time()
    
    print(f"\n--- İşlem Tamamlandı ---")
    print(f"Toplam Süre: {end_total_time - start_total_time:.2f} saniye")
    
    # Sonuçları incele
    # for res in results:
    #     print(f"Task {res[0]} - Durum: {res[1]}")

if __name__ == "__main__":
    asyncio.run(main())

Bu kodu çalıştırdığınızda, çıktıda şunu net olarak göreceksiniz:

İlk 10 görev “İzin alındı, işleme başlıyor” diyecek. Diğerleri bekleyecek. İlk 10 görevden biri biter bitmez (örn. “[Task 3] Cevap alındı”), bekleyen 11. görev (örn. “[Task 11] İzin alındı…”) hemen başlayacaktır.

Sistem, API limitinizi asla aşmaz, bu sayede 429: Too Many Concurrent Requests hatasını hiç almazsınız. Aynı zamanda asyncio sayesinde sisteminiz bloke olmaz ve son derece verimli çalışır.

Bölüm 6: Kalıcı Çözüm (3): Gerçek Bir İş Kuyruğu (Job Queue) Sistemi

Semafor çözümü harikadır, ancak tek bir uygulama örneği (instance) içinde çalışır. Peki ya uygulamanız birden fazla sunucuya (node) dağıtılmışsa (load balanced)? Veya ya API’ye göndereceğiniz işler farklı servislerden geliyorsa?

  • Bir kullanıcı web arayüzünden bir rapor istiyor (İstek 1).
  • Arka planda çalışan bir cron job (zamanlanmış görev) 1000 makaleyi özetliyor (İstek 2-1001).
  • Başka bir mikroservis, kullanıcı yorumlarını analiz ediyor (İstek 1002-2000).

Eğer bu üç servis de kendi asyncio.Semaphore(10) mantığını kullanırsa, toplamda OpenAI’ye $10 + 10 + 10 = 30$ eşzamanlı istek göndermeye çalışırlar ve limitiniz 10 ise yine hata alırsınız.

Bu noktada, merkezi bir iş kuyruğu (Job Queue) sistemine ihtiyacınız vardır.

Mimari:

  1. İstek Üreticileri (Producers): API’ye istek göndermesi gereken tüm servisleriniz (web sunucunuz, cron job’unuz, mikroservisiniz) istekleri kendileri göndermez. Bunun yerine, isteği ve parametrelerini (model, prompt, vb.) merkezi bir kuyruğa (örn. RabbitMQ, Redis veya Kafka) “iş” (job) olarak ekler.
  2. Kuyruk (Queue): Bu sistem, tüm işleri sırayla tutan bir aracıdır.
  3. İşleyiciler (Workers): Ayrı bir sunucuda (veya sunucu grubunda) çalışan, “Worker” adını verdiğimiz özel bir servis bulunur. Bu servisin tek görevi, kuyruktan işleri çekmek ve OpenAI API’sine göndermektir.

Anahtar Nokta: Sadece ve sadece Worker servisinin OpenAI API anahtarına erişimi vardır. Ve bu Worker servisini, toplamda sadece API limitiniz kadar (örn. 10) paralel iş yapacak şekilde yapılandırırsınız.

Bu mimari, “Too Many Concurrent Requests” sorununu tamamen ortadan kaldırır.

Neden Bu Mükemmel Çözümdür?

  • Merkezi Kontrol: Eşzamanlılık tek bir yerden (Worker servisi) yönetilir. Artık hangi servisin ne kadar istek gönderdiğini dert etmenize gerek yok.
  • Dayanıklılık (Resilience): OpenAI API’si 10 dakika çökerse ne olur? Hiçbir şey. İşler kuyrukta güvenle bekler. API geri geldiğinde, Worker’lar kaldığı yerden devam eder. Kullanıcıya hata dönmezsiniz.
  • Ölçeklenebilirlik: API limitiniz 10’dan 100’e mi çıktı? Tek yapmanız gereken Worker servisinizin paralel çalışma kapasitesini 10’dan 100’e çıkarmak. Diğer servislerinize dokunmanıza gerek yok.
  • Asenkron İşleme: Kullanıcınız bir istek gönderdiğinde, web sunucunuz işi saniyeden kısa sürede kuyruğa atar ve kullanıcıya “İsteğiniz alındı, işleniyor, bittiğinde size haber vereceğiz” (genellikle bir “iş ID’si” ile) yanıtını döner. Kullanıcı, API yanıtını dakikalarca beklemek zorunda kalmaz.

Python Celery ve RabbitMQ ile Örnek Mimarisi

Bu sistemi kurmanın en popüler yollarından biri Python dünyasında Celery (iş kuyruğu framework’ü) ve RabbitMQ (mesaj kuyruğu aracısı) kullanmaktır.

1. Kurulum:

pip install celery openai

Ayrıca sisteminize RabbitMQ kurmanız gerekir (veya bulut tabanlı bir servis kullanabilirsiniz).

2. Celery Yapılandırması (celery_app.py):

Python

from celery import Celery
import openai

# RabbitMQ'nun adresini veriyoruz (broker)
# Sonuçları da Redis'te saklayabiliriz (backend)
app = Celery('tasks',
             broker='amqp://guest:guest@localhost//',
             backend='redis://localhost:6379/0')

client = openai.OpenAI()

@app.task(
    bind=True,
    # Celery'ye bu görevin RateLimitError alırsa
    # exponential backoff ile yeniden denemesini söylüyoruz!
    autoretry_for=(openai.RateLimitError,),
    retry_kwargs={'max_retries': 5, 'countdown': 5} # 5s, 10s, 15s...
)
def process_openai_request(self, model, messages):
    """
    Bu, Celery Worker'ımızın çalıştıracağı asıl görev.
    """
    try:
        print(f"Görev {self.request.id} işleniyor...")
        response = client.chat.completions.create(
            model=model,
            messages=messages
        )
        return response.choices[0].message.content
    except openai.RateLimitError as e:
        print(f"Rate Limit Hatası! {self.request.id} yeniden denenecek...")
        raise e # Yeniden denenmesi için hatayı tekrar yükselt
    except Exception as e:
        print(f"Kalıcı Hata: {e}")
        return f"Hata: {str(e)}"

3. Web Sunucusu Tarafı (İşi Kuyruğa Atan – Producer):

Bu bir Flask, Django veya FastAPI uygulaması olabilir.

Python

# flask_app.py
from flask import Flask, request, jsonify
from celery_app import process_openai_request # Celery görevimizi import ediyoruz

app = Flask(__name__)

@app.route('/ask-gpt', methods=['POST'])
def ask_gpt():
    prompt = request.json.get('prompt')
    if not prompt:
        return jsonify({"error": "Prompt eksik"}), 400

    # API'yi doğrudan ÇAĞIRMIYORUZ!
    # Bunun yerine, işi kuyruğa atıyoruz.
    # '.delay()' görevi asenkron olarak kuyruğa gönderir.
    task = process_openai_request.delay(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}]
    )
    
    # Kullanıcıya işin başladığını ve takip ID'sini veriyoruz.
    return jsonify({
        "message": "İsteğiniz alındı, işleniyor.",
        "task_id": task.id
    }), 202 # 202 Accepted (Kabul Edildi)

if __name__ == '__main__':
    app.run(debug=True)

4. Worker’ı Çalıştırma (Tüketici – Consumer):

Şimdi sihirli kısım. Ayrı bir terminalde Worker’ımızı başlatırız.

Bash

# Bu komut, Celery'ye RabbitMQ'yu dinlemesini söyler.
# '-c 10' parametresi ise bizim "Concurrency Limit"imizdir!
# Bu worker, aynı anda en fazla 10 işi çalıştıracaktır.
celery -A celery_app worker --loglevel=info --concurrency=10

Artık web sunucunuza 1000 kullanıcı aynı anda /ask-gpt endpoint’ine istek atsa bile, Flask anında 1000 cevabı döner (202 Accepted) ve 1000 işi kuyruğa atar.

Arka planda çalışan Celery worker’ımız ise bu 1000 işi kuyruktan birer birer (veya bizim belirlediğimiz eşzamanlılık limiti kadar, yani 10’ar 10’ar) çekip güvenli bir şekilde OpenAI’ye gönderir.

“Too Many Concurrent Requests” hatası? Tamamen çözüldü.

Bölüm 7: Limit Artışı Talebi ve Proaktif İzleme

Teknik çözümleri uyguladınız. Kuyruk sisteminiz tıkır tıkır işliyor. Ancak kuyruktaki işler çok fazla birikmeye başladı, çünkü saniyede 10 istek size yetmiyor. Artık teknik bir sorununuz yok, kapasite sorununuz var.

Bu noktada OpenAI’den limit artışı talep etme zamanı gelmiştir.

Limit Artışı Nasıl Talep Edilir?

  1. OpenAI Dashboard’unuzdaki “Limits” sayfasına gidin.
  2. Genellikle “Request limit increase” (Limit artışı talep et) butonu bulunur.
  3. Bu bir form açacaktır. Bu formu doldururken çok spesifik olmalısınız.

İyi Bir Talep Formu Nasıl Doldurulur?

  • Ne İstediğinizi Söyleyin: “Mevcut GPT-4o eşzamanlılık limitim 10. Bunu 50’ye çıkarmak istiyorum.”
  • Neden İstediğinizi Açıklayın (Kullanım Senaryosu): “Kullanıcılarımıza gerçek zamanlı müşteri desteği sunan bir chatbot uygulamamız var. Yoğun saatlerde eşzamanlı kullanıcı sayımız 30’a çıkıyor ve bu da iş kuyruğumuzda gecikmelere neden oluyor.”
  • Mevcut Optimizasyonlarınızı Gösterin (En Önemlisi): “Halihazırda ‘Too Many Concurrent Requests’ hatalarını önlemek için merkezi bir RabbitMQ kuyruk sistemi ve 10 eşzamanlı worker’a sahip bir Celery mimarisi kullanıyoruz. Ayrıca tüm API çağrılarımızda tenacity kütüphanesi ile exponential backoff uyguluyoruz. Sistemimiz mevcut limitinde %100 verimlilikle çalışıyor ancak talebi karşılayamıyor.”

Son madde, OpenAI’ye “Ben acemi değilim, altyapımı doğru kurdum, sadece daha fazla kapasiteye ihtiyacım var” mesajını verir. Bu tür taleplerin onaylanma olasılığı çok daha yüksektir.

Proaktif İzleme (Monitoring)

Sorunun tekrar oluşmasını beklemeyin. Sisteminizi izleyin.

  • Kuyruk Uzunluğu: Kuyruğunuzdaki iş sayısı (queue depth) artıyor mu? Bu, worker’larınızın gelen iş yüküne yetişemediğinin (yani limit artışına ihtiyacınız olduğunun) ilk işaretidir.
  • Hata Oranları (Error Rates): Exponential backoff kullanıyor olsanız bile, 429 hatalarını izleyin. Eğer bu hataların sayısı artıyorsa, semafor veya kuyruk limitiniz, API limitinizden yüksek ayarlanmış olabilir.
  • API Yanıt Süreleri (Latency): OpenAI’nin yanıt sürelerini (p95, p99) izleyin. Eğer yanıt süreleri genel olarak artıyorsa, bu eşzamanlılıkta daha fazla zorlanmaya neden olabilir.

Bir Hatadan Mimariye Yolculuk

“Too Many Concurrent Requests” hatası, basit bir hata mesajından çok daha fazlasıdır. O, uygulamanızın ölçeklenme ihtiyacını haber veren bir postacıdır.

Bu 3000 kelimelik yolculukta gördüğümüz gibi, çözümler bir “yama”dan gerçek bir mimari dönüşüme doğru evrilir:

  1. Panik (Kötü Fikir): time.sleep() kullanarak sistemi körlemesine yavaşlatmak. Verimsizdir ve sorunu çözmez.
  2. Dayanıklılık (İyi Başlangıç): Exponential Backoff (örn. tenacity ile) kullanarak geçici hataları akıllıca yönetmek. Bu, hataları tolere etmenizi sağlar.
  3. Proaktif Kontrol (İyi Çözüm): asyncio.Semaphore kullanarak uygulamanızın içinde eşzamanlılığı kısıtlamak. Bu, hatayı almanızı engeller.
  4. Mimari Çözüm (En İyi Çözüm): Merkezi bir İş Kuyruğu (örn. Celery + RabbitMQ) kurarak tüm sisteminizin eşzamanlılığını tek bir, ölçeklenebilir ve dayanıklı noktadan yönetmek.

Bugün binlerce kullanıcısı olan her büyük uygulama, bu dersleri (genellikle zor yoldan) öğrenmiştir. API’lerle çalışmak, sadece istek göndermek değil, aynı zamanda bu isteklerin akışını bir orkestra şefi gibi yönetmektir.

Artık bu hatayla karşılaştığınızda ne yapacağınızı biliyorsunuz. Paniklemeyin. Bu bir sorun değil, bu bir optimizasyon davetidir. Mimarınızı seçin, kodunuzu yazın ve uygulamanızın sorunsuz bir şekilde milyonlarca isteğe ölçeklenmesini keyifle izleyin.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Hemen Arayın!