ASP.NET Core’da Gelişmiş Rate Limiting Rehberi: API’lerinizi Güvence Altına Alın
Modern web mimarilerinde bir API'yi yayına almak, onu dünyanın her yerinden gelebilecek isteklere açmak demektir. Ancak her sistemin bir kapasitesi vardır. Rate Limiting (Hız Sınırlama), belirli bir zaman diliminde bir istemcinin yapabileceği istek sayısını kısıtlayarak sisteminizi DDoS saldırılarından, bot trafiğinden ve kaynak tükenmesinden korur. ASP.NET Core 7 ve sonraki sürümlerde bu özellik, Microsoft.AspNetCore.RateLimiting kütüphanesi ile yerleşik olarak sunulmaktadır.
ASP.NET Core Yerleşik Rate Limiting Algoritmaları
ASP.NET Core, farklı kullanım senaryolarına uygun dört temel algoritma sunar. Hangi algoritmayı seçeceğiniz, uygulamanızın trafik karakteristiğine bağlıdır. Algoritmaların detaylı çalışma mantığı için .NET Mühendislik Bloğu'nu inceleyebilirsiniz.
- Fixed Window (Sabit Pencere): Belirli bir zaman dilimi (örn: 1 dakika) için sabit bir limit belirler.
- Sliding Window (Kayan Pencere): Süreyi segmentlere ayırarak sınır noktalarındaki trafik yığılmalarını (burst) engeller.
- Token Bucket (Jeton Kovası): Belirli aralıklarla dolan bir havuzdan jeton tüketerek esnek bir kısıtlama sağlar.
- Concurrency (Eşzamanlılık): Aynı anda işlenen aktif istek sayısını sınırlayarak kaynak kullanımını kontrol eder.
1. Servis Kaydı ve Politika Tanımlama
Rate limiting yapılandırması Program.cs dosyasında başlar. İşte Token Bucket algoritmasını kullanan örnek bir yapılandırma:
builder.Services.AddRateLimiter(options =>
{
options.AddTokenBucketLimiter(policyName: "CustomTokenPolicy", opt =>
{
opt.TokenLimit = 100; // Maksimum kapasite
opt.ReplenishmentPeriod = TimeSpan.FromMinutes(1);
opt.TokensPerPeriod = 20;
opt.QueueLimit = 5; // Limiti aşan isteklerin bekletileceği kuyruk
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
// HTTP 429 Too Many Requests yanıtını özelleştirme
options.OnRejected = async (context, token) =>
{
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
await context.HttpContext.Response.WriteAsync("Çok fazla istek gönderdiniz. Lütfen bekleyin.", token);
};
});
2. Middleware Kullanımı
Yönlendirme mekanizmasının bu politikaları tanıması için middleware hattına eklenmesi şarttır. Middleware sıralaması performans açısından kritiktir.
var app = builder.Build();
app.UseRouting();
app.UseRateLimiter(); // Yönlendirmeden hemen sonra gelmelidir
app.UseAuthorization();
app.MapControllers();
app.Run();
3. Kullanıcı Bazlı (IP veya User ID) Sınırlama
Genel limitler yerine her kullanıcıyı kendi özelinde sınırlamak için PartitionedRateLimiter kullanılır. Bu, RFC 6585 standartlarına uygun bir kullanıcı deneyimi sağlar:
options.AddPolicy("UserBasedPolicy", httpContext =>
{
// IP adresini anahtar (partition key) olarak kullan
var clientIp = httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
return RateLimitPartition.GetFixedWindowLimiter(clientIp, _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 10,
Window = TimeSpan.FromSeconds(30)
});
});
Sonuç ve Öneriler
Rate Limiting, sadece bir güvenlik önlemi değil, aynı zamanda API kalitesini artıran bir mimari unsurdur. Dağıtık sistemlerde (Distributed Systems) daha stabil bir çözüm için bu yapıyı Redis tabanlı bir IDistributedCache ile entegre etmeyi düşünebilirsiniz. Daha fazla detay için Microsoft'un güncel dokümantasyonuna göz atabilirsiniz.