.NET 7 ile Rate Limiting Yapısı

Bu yazımda, .NET 7 ile gelen Rate Limiting middleware yapısı ve kullanımına değinilecektir. Öncelikle Rate Limiting'in ne olduğuna değinecek olursak;

Rate Limiting, "belirli bir zaman diliminde; uygulamaya yapılan istek sayısının sınırlandırılmasıdır" ve bu amaçla uygulanan algoritmalar bulunur. 

Geliştirici olarak API entegrasyonu yaparken veya son kullanıcı olarak istek yaparken, 429 hata kodu bulunan veya "Too Many Request" mesajlı bir uyarı gördüğünüzde yapabileceğiniz istek sınırına ulaşmış olup, daha fazlasına izniniz yok demektir. Bu sınırlamayı yapan yaklaşım, rate limiting'dir.

Client Server Rate Limiting İlişkisi

Güvenlik, kaynakların doğru yönetimi, uygulamanın çökmesini engelleme ve sunucu trafiğinin kontrol altına alınması yönünden kritik bir konudur.


1 Temmuz 2023 tarihinde, Twitter'da uygulandığı açıklanan tweet görüntüleyebilme sınırını uygulayan yaklaşım da aynıdır.


"Rate Limiting Kavramını ve Algoritmalarını Anlamak"  konulu yazımda rate limiting algoritmalarına detaylı olarak değinilmiştir. Okumak için tıklayınız.

Bu yazımda, Rate Limiting kavramının .NET teknolojisinde nasıl uygulandığına değinilmektedir. 

.NET 7 ile built-in-middleware olarak gelen RateLimiting, .NET 7'den önce third party kütüphanelerin projelere dahil edilmesi veya custom middleware yazılmasını gerektirirdi.

.NET 7 de aşağıdaki Nuget paketleri, bu özelliği sağlamaktadır.

  • Microsoft.AspNetCore.RateLimiting
  • System.Threading.RateLimiting

Örnek bir projede incelemek gerekirse;

API projesi oluştururken minimum versiyon olarak .NET 7 seçili olmalıdır. 


Proje oluştuktan sonra, Program.cs dosyasına UseRateLimiter() middleware metodu dahil edilmelidir. Bu metot, uygulamada Rate Limiting'i aktif eder.


Aktifleştirdikten sonra builder.Services.AddRateLimiter servis metodu dahil edilecektir.

Bu metotla rate limiting servisleri ve içerisine policy tanımlanarak yapılandırma işlemi gerçekleştirilir. 
RateLimiterOptions türünden yapılandırma parametresi geçilir. 
  • Hangi algoritma kullanılacağı, 
  • İstek sınırlandırma işlemleri,
  • İstek reddedildiğinde nasıl dönüş yapılacağının
 yapılandırması burada yapılır.


AddRateLimiter metodundaki options içerisinde kullanılan;

options.RejectionStatusCode: İstek reddedildiğinde gösterilecek hata durum kodu ayarlanır. Varsayılan olarak 500 olacaktır. En iyi kullanım olarak 429 verilebilir.


options.OnRejected: İstek reddedildiğinde olay mantığında çalışacak işlemler tanımlanır. Loglama işlemi yapmak istersek çözüm olabilir.

options.
RateLimiter: 
Rate Limiting algoritmalarının ve yapılandırmalarının belirtileceği yerdir.
Burada kullanılan ve temel rate limiting algoritmalarına karşılık gelen metotları tanıtmaya gelince; 

AddFixedWindowLimiter()

Bu metot, Fixed Window algoritmasının uygulanmasıdır. 

Belirlenen sabit zaman aralığında istek limitine ulaşıldığında, bir sonraki zaman penceresine kadar gelen istekler reddedilecektir. 

Metotta kullanılan parametreler;
policyName: Fixed Window olarak oluşturulan policy'e verilen isim. API controller veya action metotlarda kullanılacaktır.
configureOptions: Yapılandırma ayarları burada tanımlanır. 
Action<FixedWindowRateLimiterOptions> türündedir. 
  • options.Window: İsteklerin gerçekleşeceği zaman aralığıdır. TimeSpan türünden değer atanır.
  • options.PermitLimit: Window property'sindeki zaman aralığında kabul edilecek istek adeti.
  • options.QueueLimit: Eğer belli bir zaman aralığında maksimum istek sayısına ulaşıldığında kuyruğa ne kadar istek alınabileceği tanımlanır. 
  • options.QueueProcessingOrder: Kuyrukların işlenme sırası belirtilir. Değer olarak Kuyruğa ilk gelenin ilk işleneceği OldestFirst veya kuyruğa en son girenin ilk işleneceği NewestFirst enum atanır. 
Örnek kodda, Fixed Window algoritması kullanarak sistemin 60 saniye içerisinde en fazla 12 isteği kabul edeceği ve 12 den fazla istek geldiğinde kuyruğa da en fazla 2 isteği dahil edeceğini ifade ederiz. Kuyruğa eklenen isteklerden de ilk gelenin işlenebileceği tanımlandı.


AddSlidingWindowLimiter()

Bu metot, Sliding Window algoritmasının uygulanmasıdır. 

İstekleri sabit bir zaman penceresinde sınırlamaz. Gelen istekler, istek zamanıyla birlikte bir dizi yapısında tutulur. 


Metotta kullanılan parametreler; 
policyName: Sliding Window olarak oluşturulan policy'e verilen isim. API controller veya action metotlarda kullanılacaktır.
configureOptions:Yapılandırma ayarları burada tanımlanır. 
Action<SlidingWindowRateLimiterOptions> türündedir. Ortak parametrelerden farklı olan özellikler ise;
  • options.SegmentPerWindow: İsteklerin gerçekleşme zamanının kaç eşit parçaya bölüneceğini belirtir. Yukarıdaki görselde 10 saniyelik zaman penceresinin 1 eşit parçaya bölündüğü ve 10 saniyede 50 istek kabul edileceğini belirtir. 
AddTokenBucketLimiter()

Bu metot, Token Bucket algoritmasının uygulanmasını sağlar.

Belirli bir periyotta belirli bir sayıda istek yapabileceğini belirleriz.


Metotta kullanılan parametreler; 
policyName: Token Bucket olarak oluşturulan policy'e verilen isim. API controller veya action metotlarda kullanılacaktır.
configureOptions:Yapılandırma ayarları burada tanımlanır. 
Action<TokenBucketRateLimiterOptions> türündedir. Ortak parametrelerden farklı olan özellikler ise;
  • options.TokenPerPeriod: Her yenilenme zamanında eklenmesi istenen maksimum istek limitidir.
  • options.TokenLimit: Herhangi bir zamanda belirtilen en fazla istek limitidir.
Örnek olarak;

TokenPerPeriod=7 ve TokenLimit=10 olan bir problemde her yenilenme zamanında 7 adet istek limiti olacaktır. İsteğin başında 10 verilmektedir. Eğer istek artarsa yenilemede, 7 olarak sınır belirtilir.

AddConcurrencyLimiter()

Bu metot, sadece asenkron istekleri sınırlandırmamızı sağlar. 


Metotta kullanılan parametreler; 
policyName: Concurrency Limiter olarak oluşturulan policy'e verilen isim. API controller veya action metotlarda kullanılacaktır.
configureOptions:Yapılandırma ayarları burada tanımlanır. 
Action<ConcurrencyLimiterOptions> türündedir. 
  • options.PermitLimit: Asenkron olarak en fazla gerçekleşebilecek istek adetidir.
Örneği daha iyi anlayabilmek için örnek bir kod yapısına Task.Delay ile 10 saniye bekletme yapılan bir iş kuralı oluşturup birden fazla sekmede aynı endpointi çağırabilirsiniz.



Attribute - Özellikler

Rate Limiting politikalarının uygulanabilmesi için aktif ve pasif yapılabilen iki adet attribute bulunur. Bunlar, controller ve metot seviyelerinde tanımlanabilir. 
Controller seviyesinde tanımlananlar,  o controller altındaki bütün endpointlerde geçerlidir.
Metotlarda tanımlananlar ise o endpointler için geçerlidir.

EnableRateLimiting: Program.cs'de tanımlanan ratelimiter politikasının ismini parametre olarak vererek controller veya metotta kullanılmasını sağlar.


DisableRateLimiting: RateLimiting kullanılmasını engeller. Aşağıdaki görselde bulunan endpoint için rate limiting çalışmayacaktır.


Bonus: Minimal API'de
kullanmak için RequireRateLimiting metoduna parametre olarak policy ismi verildikten sonra çalışacaktır.


Özetle;

RateLimiting yapısını kısaca tanımlayarak .NET 7 ile yapılandırılması ve kullanımına değinilmiştir.

Örnek Github reposuna ulaşmak için buraya tıklayabilirsiniz. 

Keyifli ve faydalı olmasını umarak, çalışmalarınızda kolaylıklar diliyorum. 

Yazımı yazarken incelediğim kaynaklar,

Yorumlar