VDS (Sanal Özel Sunucu) üzerinde çalışan Python uygulamaları, özellikle asyncio kullanılarak yazılanlar, beklenmedik yavaş yanıt süreleriyle karşılaşabilir. CPU kullanımı düşük görünse bile, işlemler tıkanıyor ve kullanıcılar zaman aşımı hataları alıyorlar. Çoğu zaman bu sorunun nedeni, event loop'un bloke edilmesidir—yani ağır işlemler ana thread'i tutarak, diğer işlerin yapılmasını engellemesidir.

Event Loop Nedir ve Neden Tıkanır?

Python'un asyncio kütüphanesi, olay temelli (event-driven) programlamayı sağlar. Tek bir thread'de binlerce eş zamanlı bağlantıyı yönetebilir. Fakat bir sorun vardır: event loop'a gönderilen görev eğer I/O olmayan (CPU-bound) ağır işlemse, o görev tamamlanana kadar diğer görevler beklemek zorunda kalır.

Örneğin, JSON parsing, veri işleme, şifreleme veya döngü hesaplaması yapan bir fonksiyon, event loop'u saniye ile ölçülen süreler boyunca bloke edebilir. Bu süre zarfında, diğer bağlı kullanıcıların istekleri yanıt alamamaktadır.

Event Loop Tıkanmasını Tanılamak

Sorunu çözmek için önce tespit etmeniz gerekir. VDS'de kullanabileceğiniz yöntemler:

  • Asyncio debug modu: asyncio.run(main(), debug=True) ile event loop'un gecikme sürelerini görebilirsiniz.
  • Python Profiler: cProfile veya py-spy ile hangi fonksiyonların en çok zaman aldığını bulabilirsiniz.
  • İstek yanıt zamanı analizi: API response time'ı ölçerek, belirli endpoint'lerin geciktiğini tespit edin.
  • Event loop callback gecikmeleri: asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) yerine asyncio.new_event_loop() ile loop oluşturup, içine debug callback ekleyin.

CPU-Bound İşlemleri executor'a Taşıyın

asyncio'nun event loop'unu koruma yollarından biri, ağır işlemleri ayrı thread havuzuna (ThreadPoolExecutor) veya process havuzuna (ProcessPoolExecutor) taşımaktır.

await loop.run_in_executor(executor, heavy_function, args) ile yapabilirsiniz. Örneğin:

  • JSON parsing veya serialization → ThreadPoolExecutor
  • Matematik hesaplamaları, döngü işlemleri → ProcessPoolExecutor
  • Şifreleme/hash işlemleri → ThreadPoolExecutor (I/O wait'i var)

Bu şekilde, ağır görev başka thread'de çalışırken, event loop diğer bağlantılara hizmet vermeye devam eder.

Async Kütüphaneleri Tercih Edin

Veritabanı sorgusu, HTTP isteği veya dosya okuma gibi I/O işlemleri için, senkron kütüphaneler yerine async versiyonlarını kullanın:

  • requests → aiohttp veya httpx
  • psycopg2 → asyncpg (PostgreSQL için)
  • mysql.connector → aiomysql
  • json parsing → orjson veya ujson (daha hızlı)

Senkron kütüphaneler, executor aracılığıyla çağırılsa bile, veritabanı bağlantı havuzu yönetimi uygun olmayabilir.

Event Loop Boyutunu VDS Kaynağına Göre Ayarlayın

VDS'nin CPU çekirdek sayısına göre, ProcessPoolExecutor havuz boyutunu ayarlayın:

  • Varsayılan: min(32, os.cpu_count() + 4)
  • VDS çekirdeği az ise, havuz boyutunu azaltın: ProcessPoolExecutor(max_workers=2)
  • ThreadPoolExecutor içinse, havuz boyutu daha büyük olabilir: ThreadPoolExecutor(max_workers=10)

Fazla worker açarsanız, context switching overhead'i artar ve performans düşer.

Asyncio Task Timeout Belirleyin

Tıkanan görevlerin sistem öldürmesi yerine, timeout koyarak hata döndürün:

  • asyncio.wait_for(coro, timeout=5.0) ile 5 saniye sonra TimeoutError kaldırın.
  • Web framework'te global request timeout'u ayarlayın (FastAPI, aiohttp vb.).
  • Veritabanı bağlantı timeout'u, sorgu timeout'undan ayrı ayarlayın.

Sonuç

VDS üzerinde Python asyncio uygulamasını yavaşlayan sorunu çözmenin anahtarı, event loop'un bloke edilmesini önlemek ve I/O işlemleri için async kütüphaneler kullanmaktır. Ağır işlemleri executor'a taşıyarak, timeout tanımlayarak ve async versiyonlarıyla değiştirerek, çok daha verimli ve yanıt verme hızı yüksek bir sistem elde edebilirsiniz.

Bogahost'un yüksek performanslı VDS çözümleriyle, Python uygulamalarınızı optimal şekilde çalıştırabilir ve gerektiğinde kaynakları hızlıca artırabilirsiniz.