API Throttling nedir?
API throttling, bir kullanıcının belirli bir süre içerisinde yapacağı API isteklerinin oransal olarak denetlenerek, sınırlandırılması ve kısıtlanmasıdır.
Böylelikle bir kaynağın ya da uygulamanın fazla kullanımının, sömürüsünün önüne geçebilirsiniz.
Bir istek yapıldığında limit değer aşılmışsa istek başarısız olur ve HTTP 429 Too Many Requests cevabı istemciye döndürülür.
Gerçek birkaç senaryo üzerinden örnekleyecek olursak;
- Kullanıcıların bir gün içerisinde maksimum 10 dosya upload edebilmesi.
- Üyelik tipine sahip bir uygulamanın, üyelik tipine göre kullanıcılarına işlem yetkisi tanımlaması. Örneğin premium kullanıcı bir servisi saatte 100 defa kullanılabilir fakat normal bir kullanıcı sadece 5 istek çıkabilir vs.
API throttling, uygulamaları daha hızlı, daha güvenli ve fiyatlandırabilir kılmakta ve günümüzde fazlasıyla kullanılmaktadır.
Django Rest Framework API Throttling.
DRF’in sahip olduğu throttle mekanizması, permission ve authentication mekanizmaları gibi pluggable bir yapıdadır. Proje genelinde uygulanabileceği gibi, tek bir view üzerinde de uygulanabilir.
Throttle sınıfları, yine permission ya da authentication sınıfları gibi tuple yada list olarak tanımlanmak zorundadır.
Nasıl çalışır?
İstek yapıldığında, ilgili view gövdesi çalıştırılmadan önce tüm throttle sınıfları, isteğin uygunluğunu kontrol eder, herhangi bir kontrol sınıfında, kontrole takılan bir durum varsa rest_framework.exceptions.Throttled hatası fırlatılır ve view gövdesi çalıştırılmadan kullanıcıya 429 Too Many Request cevabı döndürülür.
DRF yerleşik olarak 3 adet throttle sınıfına sahiptir.
- AnonRateThrottle (Anonim kullanıcı limitleme.)
- UserRateThrottle (Authenticate olmuş kullanıcı limiti.)
- ScopedRateThrottle (API’nızın farklı kısımlarının, farklı rate limit ile çalışabilmesi için kurgulanır.)
Throttle sınıflarının limitleri {“scope” : “rate_limit”} formatında tanımlanır.
Rate limitler saniye, dakika, saat ve gün zaman oranı ile belirlenebilir.
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES': { 'anon': '3/day', 'user': '10/day' } }
Yukarıdaki settings global olarak, anonim kullanıcılar için günde 3, oturum açmış kullanıcılar içinse günde 10 isteğe izin veren bir yapıdadır.
AnonRateThrottle için varsayılan scope değeri “anon”, UserRateThrottle içinse “user” dır.
Basit bir view yazıp kontrol edelim.
from rest_framework.views import APIView from rest_framework.response import Response class ExampleView(APIView): def get(self, request, format=None, *args, **kwargs): return Response({"message": "Hello world."})
Doğrulanmamış bir kullanıcı ile 3 adet istek çıktıktan sonra 4. istek sonucu dönen cevap;
$ http --body localhost:8080/api/example/ { "detail": "Request was throttled. Expected available in 86295 seconds." }
İstek global olarak kaydettiğimiz 2 throttle sınıfı üzerinde değerlendirildi ve AnonRateThrottle tarafından yapılan kontrolden geçemediği için view gövdesi çalıştırılmadan uygulamamız 429 statü koduna sahip cevabı döndü.
Eğer authenticate olmuş olsaydık;
$ http localhost:8080/api/example/ 'Authorization:Token d68b2b6dadb267860e0d4e64beed261a18eaff1f'
Bu sefer, UserRateThrottle sınıfı 11. istekte Throttled exceptionı fırlatacak ve view gövdesi çalıştırılmadan, HTTP 429 Too Many Requests statü kodu ile ilgili cevap dönecektir.
ScopedRateThrottle.
Eğer uygulama genelinde bir throttle mekanizmasına sahip ve API’nızın farklı kısımlarına erişimi dinamik olarak değiştirmek istiyorsanız ScopedRateThrottle sınıfını kullanabilirsiniz.
Tek bir throttle sınıfı üzerinden sadece scope rate değerleri girerek erişimi denetleyebilirsiniz.
Örneğin bir ticket sisteminde kullanıcıya ticketları günde 1000 defa listemeleye izin verirken, dosya upload edeceği endpointe günlük 10 limiti koyarak bir denetleme yapmak isteyebiliriz.
REST_FRAMEWORK = { "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.ScopedRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "file_upload" : "10/day", "list_ticket" : "1000/day", }, }
View üstünde scope belirtelim;
class UplaodFileView(APIView): throttle_scope = "file_upload" def post(self, request, *args, **kwargs): return Response({"message": "file uploaded."}) class TicketListView(APIView): throttle_scope = "list_ticket" def get(self, request, *args, **kwargs): return Response([])
Böylece proje genelinde çalışan throttle mekanizması, farklı scopelarda farklı denetim oranları ile değerlendirme yapıyor.
Global olarak ScopedRateThrottle mekanizması kullanıldığında, view üzerinde scope belirtilmezse herhangi bir kısıtlamaya uygulanmayacaktır.
Custom bir throttle sınıfı oluşturmak.
Uygulamamızda özelleştirilmiş bir kısıtlama mekanizması oluşturacak isek, BaseThrottle sınıfını miras alarak, allow_request(self, request, view) metodunu özelleştirebiliriz. Kontrol sonucu, isteğe izin verecek isek bu metod True, tersi durumda False döndürülmedir.
Örneğin;
from rest_framework import throttling class CEOUserThrottle(throttling.UserRateThrottle): def allow_request(self, request, view): if request.user.email == "ceo@office.com": return True return super().allow_request(request, view)
class ExampleView(APIView): throttle_classes = [CEOUserThrottle] def get(self, request, format=None, *args, **kwargs): return Response({"message": "Hello world."})
Giriş yapmış normal kullanıcılar için limitler dahilinde kısıtlama uygulanacak, isteği atan kullanıcı ceo ise bir kısıtlamaya tabi tutulmayacaktır.
Sonuç.
Throttling işlemi, API geliştirme süreçlerinde, uygulamanızın fiyatlandırılabilmesi, ölçeklenebilmesi ya da dış servislerle kurulan isteklerin kontrol altında tutulabilmesi için önemli bir konu.
Throttling hakkında ve bu konuyla alakalı DRF dökümantasyonundan daha fazla bilgi almak isterseniz;
İlk Yorumu Siz Yapın