Bir sabah sitene giriyorsun, sayfa 8-10 saniye boyunca beyaz ekranda kalıyor. Panik yapıyorsun — "sunucu mu çöktü?" Ama sayfa yükleniyor, her şey normal çalışıyor. Sonraki tıklamalar ise anında açılıyor.
Bu cold start. Uygulaman bir süre istek almadığında, IIS onu belleğe alıp kapatır. Bir sonraki istek geldiğinde, .NET runtime'ı sıfırdan ayağa kaldırmak, DbContext'i kurmak, servisleri DI container'a doldurmak gerekir — işte o birkaç saniyelik gecikme burdan gelir.
Kullanıcı için sorun değilse de, bir lisans doğrulama API'si için ciddi sorun. Müşterinin plugin'i her açılışta API'ye soruyor — API uyuyorsa, plugin donmuş gibi görünür.
Bunun sorumlusu IIS'in App Pool Idle Time-out ayarı. Bu süre sabit değil — hosting sağlayıcısına ve panel yapılandırmasına göre değişir; bazı panellerde 5 dakika kadar kısa, bazılarında 20 dakika veya daha uzun olabilir. Bir uygulama bu süre boyunca hiç istek almazsa, IIS worker process'i (w3wp.exe) kapatır. Belleği geri alır, başka siteler kullansın diye.
Dedicated bir sunucuda bu ayarı IIS Manager'dan değiştirebilirsin, hatta "Always On" moduna alabilirsin. Ama shared hosting'de bu seçenek yok — Application Pool ayarlarına erişimin kısıtlı, çünkü o pool'u sen değil, hosting firması yönetiyor.
Önce kendi panelindeki değeri öğrenmek faydalı olur (hosting firmana sorabilir ya da panel dokümantasyonuna bakabilirsin). Ama pratikte soru şu hale geliyor: IIS'i değiştiremiyorsan, uygulamanı hiç uyumasın diye nasıl "meşgul" tutarsın?
Çözüm basit bir fikre dayanıyor: idle timeout süresi dolmadan, dışarıdan uygulamana kendin bir istek gönder. Uygulama hiç boşta kalmadığı için IIS onu kapatma fırsatı bulamaz.
Bunun için önce uygulamana hafif, kimlik doğrulaması istemeyen bir "ping" endpoint'i eklemen gerekiyor:
[ApiController]
[Route("api/[controller]")]
public class PingController : ControllerBase
{
// AllowAnonymous — cron job giriş yapmıyor, sadece uyandırıyor
[HttpGet]
[AllowAnonymous]
public IActionResult Get()
{
// Ağır bir iş yapma — tek amacı process'i canlı tutmak
return Ok(new { status = "awake", time = DateTime.UtcNow });
}
}
Endpoint hazır olunca sırada, onu düzenli aralıklarla çağıracak bir zamanlayıcı var. Plesk'te bu Scheduled Tasks (Zamanlanmış Görevler) altında.
Idle timeout süresi dolmadan tetiklemek için, örneğin her 3 dakikada bir çalışan bir görev genelde yeterli pay bırakır — ama panelinin gerçek timeout süresini bilmiyorsan, önce onu öğrenmekte fayda var:
# Plesk Scheduled Task — cron ifadesi
# Her 3 dakikada bir, saatin her dakikasında (0, 3, 6, 9 ... 57)
0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * *
# Çalıştırılacak komut (curl ile)
curl -s -o /dev/null -w "%{http_code}" https://api.emreulutabak.com/api/ping
Kurulumdan sonra çözümün gerçekten çalıştığını doğrulamak lazım. Birkaç yöntem: