Rate Limiting Önemi (Detaylı Anlatım ve Güvenli Uygulama Teknikleri)
Rate Limiting (Hız Sınırlama) , bir kullanıcının, IP adresinin veya sistemin belirli bir zaman aralığında yapabileceği istek sayısını sınırlayan bir güvenlik ve performans mekanizmasıdır. Rate limiting, hem güvenlik hem de kaynak yönetimi açısından kritik bir öneme sahiptir.
Rate Limiting Neden Önemlidir?
DoS/DDoS Saldırılarını Önleme: Sistem kaynaklarının tükenmesini engeller.
Brute Force Saldırılarını Engelleme: Parola deneme, token tahmin etme gibi saldırıları zorlaştırır.
Kaynak Koruma: API'lerin, veritabanlarının ve diğer servislerin aşırı yüklenmesini önler.
API Güvenliği: API anahtarlarının kötüye kullanılmasını engeller.
Maliyet Kontrolü: Ücretli API'lerde maliyetleri kontrol altında tutar.
Hizmet Kalitesi: Tüm kullanıcılar için tutarlı performans sağlar.
Rate Limiting Stratejileri:
1. Sabit Pencere (Fixed Window)
Belirli bir zaman aralığında (örn: 1 dakika) istek sayısını sınırlar.
Örnek: Dakikada 100 istek.
Avantajları: Uygulaması basit.
Dezavantajları: Ani patlamalara karşı hassas (pencere sınırında).
2. Kayan Pencere (Sliding Window)
Zaman aralığı sürekli hareket eder, her an için istek sayısı hesaplanır.
Örnek: Son 60 saniyede 100 istek.
Avantajları: Daha adil ve doğru.
Dezavantajları: Daha karmaşık, daha fazla hafıza gerektirir.
3. Token Bucket (Token Kovası)
Belirli bir kapasitede token havuzu, her istek bir token tüketir. Token'lar belirli aralıklarla yenilenir.
Örnek: 100 token kapasite, saniyede 10 token yenilenme.
Avantajları: Patlamalara izin verir (kısa süreli yüksek trafik).
Dezavantajları: Token yenilenme hızı doğru ayarlanmalıdır.
4. Leaky Bucket (Sızdıran Kova)
İstekler bir kuyruğa alınır ve sabit hızda işlenir. Kuyruk dolduğunda istekler reddedilir.
Avantajları: Sabit işleme hızı sağlar.
Dezavantajları: Kuyruk boyutu doğru ayarlanmalıdır.
Rate Limiting Uygulama Teknikleri:
1. Redis ile Rate Limiting (Kayan Pencere)
python
import redis
import time
class RateLimiter:
def __init__(self, redis_client):
self.redis = redis_client
def is_allowed(self, key, limit, window_seconds):
"""
Kayan pencere rate limiting
key: Kullanıcı veya IP bazlı anahtar
limit: İzin verilen maksimum istek sayısı
window_seconds: Zaman penceresi (saniye)
"""
current_time = time.time()
window_start = current_time - window_seconds
# Redis sorted set kullan
pipeline = self.redis.pipeline()
# Eski istekleri temizle
pipeline.zremrangebyscore(key, 0, window_start)
# Yeni isteği ekle
pipeline.zadd(key, {str(current_time): current_time})
# İstek sayısını al
pipeline.zcard(key)
# TTL ayarla (opsiyonel)
pipeline.expire(key, window_seconds + 10)
results = pipeline.execute()
request_count = results[2] # zcard sonucu
return request_count <= limit
# Kullanım
redis_client = redis.Redis(host='localhost', port=6379, db=0)
limiter = RateLimiter(redis_client)
def rate_limited_endpoint(request):
user_id = request.user.id
key = f"rate_limit:user:{user_id}"
if limiter.is_allowed(key, limit=100, window_seconds=60):
return process_request(request)
else:
return {"error": "Rate limit exceeded. Try again later."}, 429
2. Token Bucket ile Rate Limiting
python
import time
import threading
class TokenBucket:
def __init__(self, capacity, refill_rate):
self.capacity = capacity # Maksimum token sayısı
self.refill_rate = refill_rate # Saniyede yenilenen token sayısı
self.tokens = capacity
self.last_refill = time.time()
self.lock = threading.Lock()
def refill(self):
now = time.time()
elapsed = now - self.last_refill
new_tokens = elapsed * self.refill_rate
if new_tokens > 0:
self.tokens = min(self.capacity, self.tokens + new_tokens)
self.last_refill = now
def consume(self, tokens=1):
with self.lock:
self.refill()
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
# Kullanım
bucket = TokenBucket(capacity=100, refill_rate=10) # 100 token kapasite, saniyede 10 token
def api_endpoint():
if bucket.consume():
return {"status": "success"}
else:
return {"error": "Rate limited"}, 429
3. Flask ile Rate Limiting
python
from flask import Flask, request, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
# Rate limiter yapılandırması
limiter = Limiter(
app,
key_func=get_remote_address, # IP bazlı
default_limits=["200 per day", "50 per hour"]
)
# Endpoint bazlı rate limiting
@app.route('/api/login', methods=['POST'])
@limiter.limit("5 per minute") # Dakikada 5 login denemesi
def login():
# Login işlemi
return jsonify({"status": "success"})
# Kullanıcı bazlı rate limiting
@app.route('/api/user')
@limiter.limit("10 per minute", key_func=lambda: request.headers.get('X-API-Key', 'anonymous'))
def user_endpoint():
return jsonify({"data": "user data"})
# Kayan pencere ile rate limiting
@app.route('/api/search')
@limiter.limit("100 per 60 seconds", key_func=get_remote_address)
def search():
return jsonify({"results": []})
4. Django ile Rate Limiting
python
# settings.py
INSTALLED_APPS = [
...
'django_ratelimit',
]
MIDDLEWARE = [
'django_ratelimit.middleware.RatelimitMiddleware',
...
]
RATELIMIT_USE_CACHE = 'default'
RATELIMIT_CACHE = 'default'
# views.py
from django_ratelimit.decorators import ratelimit
from django.http import JsonResponse
@ratelimit(key='ip', rate='10/m', method='POST')
def login_view(request):
if request.limited:
return JsonResponse({'error': 'Too many login attempts. Try again later.'}, status=429)
# Login işlemi
return JsonResponse({'status': 'success'})
@ratelimit(key='user', rate='100/h')
def api_view(request):
return JsonResponse({'data': 'API response'})
5. Nginx Rate Limiting
nginx
# nginx.conf
http {
# Rate limiting zone tanımlama
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
# Burst ile rate limiting
limit_req_zone $binary_remote_addr zone=burst_limit:10m rate=10r/s;
server {
location /api/ {
# Standart rate limiting
limit_req zone=api_limit burst=20 nodelay;
# Login endpoint'i için özel limit
location /api/login {
limit_req zone=login_limit burst=3;
proxy_pass http://backend;
}
# Burst ile rate limiting
location /api/search {
limit_req zone=burst_limit burst=50;
proxy_pass http://backend;
}
}
}
}
Rate Limiting En İyi Uygulamalar:
1. Katmanlı Rate Limiting
python
def multi_layer_rate_limit(request):
# 1. IP bazlı limit
ip_key = f"rate:ip:{request.ip}"
# 2. Kullanıcı bazlı limit (giriş yapmışsa)
if request.user.is_authenticated:
user_key = f"rate:user:{request.user.id}"
# 3. API anahtarı bazlı limit
api_key = request.headers.get('X-API-Key')
if api_key:
api_key_key = f"rate:apikey:{api_key}"
# 4. Global limit (tüm sistem)
global_key = "rate:global"
2. Anlamlı Hata Mesajları
python
from flask import jsonify
def rate_limit_response(retry_after):
return jsonify({
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please slow down.",
"retry_after": retry_after,
"limit": "100 per minute",
"remaining": 0
}
}), 429, {
"Retry-After": str(retry_after),
"X-RateLimit-Limit": "100",
"X-RateLimit-Remaining": "0",
"X-RateLimit-Reset": str(int(time.time()) + retry_after)
}
3. Rate Limit Header'ları
python
def add_rate_limit_headers(response, limits):
response.headers['X-RateLimit-Limit'] = str(limits['limit'])
response.headers['X-RateLimit-Remaining'] = str(limits['remaining'])
response.headers['X-RateLimit-Reset'] = str(limits['reset_time'])
return response
Rate Limiting Kontrol Listesi:
A. Rate Limiting Stratejisi:
Hangi strateji kullanılıyor? (Fixed Window, Sliding Window, Token Bucket)
İş gereksinimlerine uygun mu?
Patlama (burst) trafiğe izin veriliyor mu?
B. Limit Değerleri:
Limit değerleri doğru belirlenmiş mi?
Farklı endpoint'ler için farklı limitler var mı?
Farklı kullanıcı rolleri için farklı limitler var mı?
C. Uygulama:
Rate limiting hangi katmanda uygulanıyor? (Nginx, WAF, Uygulama)
Redis veya benzeri bir önbellek kullanılıyor mu?
Dağıtık sistemlerde paylaşımlı rate limiting var mı?
D. Hata Yönetimi:
Rate limit aşıldığında 429 status kodu dönüyor mu?
Retry-After header'ı dönüyor mu?
Rate limit header'ları (X-RateLimit-*) dönüyor mu?
E. İzleme ve Log:
Rate limit aşımları loglanıyor mu?
Anormal yüksek trafik izleniyor mu?
Alert mekanizması var mı?
Özel Senaryolar:
1. Dağıtık Sistemlerde Rate Limiting
Redis Cluster kullanarak merkezi rate limiting.
Consul veya etcd ile dağıtık rate limiting.
python
import redis
from redis import RedisCluster
# Redis Cluster ile rate limiting
redis_client = RedisCluster(
host='redis-cluster',
port=6379,
decode_responses=True
)
2. Graceful Degradation
Rate limit aşıldığında tüm istekleri reddetmek yerine, esnek davranın.
python
def adaptive_rate_limit(request):
current_load = get_system_load()
if current_load < 50:
limit = 100
elif current_load < 75:
limit = 50
else:
limit = 10
# Limit'e göre rate limiting uygula
return check_rate_limit(request, limit)
3. Client Bazlı Rate Limiting
API anahtarları veya OAuth scope'ları bazlı farklı limitler.
python
def get_client_limit(api_key):
# Veritabanından veya cache'den client limit'ini al
client = Client.objects.get(api_key=api_key)
return client.rate_limit
Rate Limiting (Hız Sınırlama) , bir kullanıcının, IP adresinin veya sistemin belirli bir zaman aralığında yapabileceği istek sayısını sınırlayan bir güvenlik ve performans mekanizmasıdır. Rate limiting, hem güvenlik hem de kaynak yönetimi açısından kritik bir öneme sahiptir.
Rate Limiting Neden Önemlidir?
DoS/DDoS Saldırılarını Önleme: Sistem kaynaklarının tükenmesini engeller.
Brute Force Saldırılarını Engelleme: Parola deneme, token tahmin etme gibi saldırıları zorlaştırır.
Kaynak Koruma: API'lerin, veritabanlarının ve diğer servislerin aşırı yüklenmesini önler.
API Güvenliği: API anahtarlarının kötüye kullanılmasını engeller.
Maliyet Kontrolü: Ücretli API'lerde maliyetleri kontrol altında tutar.
Hizmet Kalitesi: Tüm kullanıcılar için tutarlı performans sağlar.
Rate Limiting Stratejileri:
1. Sabit Pencere (Fixed Window)
Belirli bir zaman aralığında (örn: 1 dakika) istek sayısını sınırlar.
Örnek: Dakikada 100 istek.
Avantajları: Uygulaması basit.
Dezavantajları: Ani patlamalara karşı hassas (pencere sınırında).
2. Kayan Pencere (Sliding Window)
Zaman aralığı sürekli hareket eder, her an için istek sayısı hesaplanır.
Örnek: Son 60 saniyede 100 istek.
Avantajları: Daha adil ve doğru.
Dezavantajları: Daha karmaşık, daha fazla hafıza gerektirir.
3. Token Bucket (Token Kovası)
Belirli bir kapasitede token havuzu, her istek bir token tüketir. Token'lar belirli aralıklarla yenilenir.
Örnek: 100 token kapasite, saniyede 10 token yenilenme.
Avantajları: Patlamalara izin verir (kısa süreli yüksek trafik).
Dezavantajları: Token yenilenme hızı doğru ayarlanmalıdır.
4. Leaky Bucket (Sızdıran Kova)
İstekler bir kuyruğa alınır ve sabit hızda işlenir. Kuyruk dolduğunda istekler reddedilir.
Avantajları: Sabit işleme hızı sağlar.
Dezavantajları: Kuyruk boyutu doğru ayarlanmalıdır.
Rate Limiting Uygulama Teknikleri:
1. Redis ile Rate Limiting (Kayan Pencere)
python
import redis
import time
class RateLimiter:
def __init__(self, redis_client):
self.redis = redis_client
def is_allowed(self, key, limit, window_seconds):
"""
Kayan pencere rate limiting
key: Kullanıcı veya IP bazlı anahtar
limit: İzin verilen maksimum istek sayısı
window_seconds: Zaman penceresi (saniye)
"""
current_time = time.time()
window_start = current_time - window_seconds
# Redis sorted set kullan
pipeline = self.redis.pipeline()
# Eski istekleri temizle
pipeline.zremrangebyscore(key, 0, window_start)
# Yeni isteği ekle
pipeline.zadd(key, {str(current_time): current_time})
# İstek sayısını al
pipeline.zcard(key)
# TTL ayarla (opsiyonel)
pipeline.expire(key, window_seconds + 10)
results = pipeline.execute()
request_count = results[2] # zcard sonucu
return request_count <= limit
# Kullanım
redis_client = redis.Redis(host='localhost', port=6379, db=0)
limiter = RateLimiter(redis_client)
def rate_limited_endpoint(request):
user_id = request.user.id
key = f"rate_limit:user:{user_id}"
if limiter.is_allowed(key, limit=100, window_seconds=60):
return process_request(request)
else:
return {"error": "Rate limit exceeded. Try again later."}, 429
2. Token Bucket ile Rate Limiting
python
import time
import threading
class TokenBucket:
def __init__(self, capacity, refill_rate):
self.capacity = capacity # Maksimum token sayısı
self.refill_rate = refill_rate # Saniyede yenilenen token sayısı
self.tokens = capacity
self.last_refill = time.time()
self.lock = threading.Lock()
def refill(self):
now = time.time()
elapsed = now - self.last_refill
new_tokens = elapsed * self.refill_rate
if new_tokens > 0:
self.tokens = min(self.capacity, self.tokens + new_tokens)
self.last_refill = now
def consume(self, tokens=1):
with self.lock:
self.refill()
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
# Kullanım
bucket = TokenBucket(capacity=100, refill_rate=10) # 100 token kapasite, saniyede 10 token
def api_endpoint():
if bucket.consume():
return {"status": "success"}
else:
return {"error": "Rate limited"}, 429
3. Flask ile Rate Limiting
python
from flask import Flask, request, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
# Rate limiter yapılandırması
limiter = Limiter(
app,
key_func=get_remote_address, # IP bazlı
default_limits=["200 per day", "50 per hour"]
)
# Endpoint bazlı rate limiting
@app.route('/api/login', methods=['POST'])
@limiter.limit("5 per minute") # Dakikada 5 login denemesi
def login():
# Login işlemi
return jsonify({"status": "success"})
# Kullanıcı bazlı rate limiting
@app.route('/api/user')
@limiter.limit("10 per minute", key_func=lambda: request.headers.get('X-API-Key', 'anonymous'))
def user_endpoint():
return jsonify({"data": "user data"})
# Kayan pencere ile rate limiting
@app.route('/api/search')
@limiter.limit("100 per 60 seconds", key_func=get_remote_address)
def search():
return jsonify({"results": []})
4. Django ile Rate Limiting
python
# settings.py
INSTALLED_APPS = [
...
'django_ratelimit',
]
MIDDLEWARE = [
'django_ratelimit.middleware.RatelimitMiddleware',
...
]
RATELIMIT_USE_CACHE = 'default'
RATELIMIT_CACHE = 'default'
# views.py
from django_ratelimit.decorators import ratelimit
from django.http import JsonResponse
@ratelimit(key='ip', rate='10/m', method='POST')
def login_view(request):
if request.limited:
return JsonResponse({'error': 'Too many login attempts. Try again later.'}, status=429)
# Login işlemi
return JsonResponse({'status': 'success'})
@ratelimit(key='user', rate='100/h')
def api_view(request):
return JsonResponse({'data': 'API response'})
5. Nginx Rate Limiting
nginx
# nginx.conf
http {
# Rate limiting zone tanımlama
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
# Burst ile rate limiting
limit_req_zone $binary_remote_addr zone=burst_limit:10m rate=10r/s;
server {
location /api/ {
# Standart rate limiting
limit_req zone=api_limit burst=20 nodelay;
# Login endpoint'i için özel limit
location /api/login {
limit_req zone=login_limit burst=3;
proxy_pass http://backend;
}
# Burst ile rate limiting
location /api/search {
limit_req zone=burst_limit burst=50;
proxy_pass http://backend;
}
}
}
}
Rate Limiting En İyi Uygulamalar:
1. Katmanlı Rate Limiting
python
def multi_layer_rate_limit(request):
# 1. IP bazlı limit
ip_key = f"rate:ip:{request.ip}"
# 2. Kullanıcı bazlı limit (giriş yapmışsa)
if request.user.is_authenticated:
user_key = f"rate:user:{request.user.id}"
# 3. API anahtarı bazlı limit
api_key = request.headers.get('X-API-Key')
if api_key:
api_key_key = f"rate:apikey:{api_key}"
# 4. Global limit (tüm sistem)
global_key = "rate:global"
2. Anlamlı Hata Mesajları
python
from flask import jsonify
def rate_limit_response(retry_after):
return jsonify({
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please slow down.",
"retry_after": retry_after,
"limit": "100 per minute",
"remaining": 0
}
}), 429, {
"Retry-After": str(retry_after),
"X-RateLimit-Limit": "100",
"X-RateLimit-Remaining": "0",
"X-RateLimit-Reset": str(int(time.time()) + retry_after)
}
3. Rate Limit Header'ları
python
def add_rate_limit_headers(response, limits):
response.headers['X-RateLimit-Limit'] = str(limits['limit'])
response.headers['X-RateLimit-Remaining'] = str(limits['remaining'])
response.headers['X-RateLimit-Reset'] = str(limits['reset_time'])
return response
Rate Limiting Kontrol Listesi:
A. Rate Limiting Stratejisi:
Hangi strateji kullanılıyor? (Fixed Window, Sliding Window, Token Bucket)
İş gereksinimlerine uygun mu?
Patlama (burst) trafiğe izin veriliyor mu?
B. Limit Değerleri:
Limit değerleri doğru belirlenmiş mi?
Farklı endpoint'ler için farklı limitler var mı?
Farklı kullanıcı rolleri için farklı limitler var mı?
C. Uygulama:
Rate limiting hangi katmanda uygulanıyor? (Nginx, WAF, Uygulama)
Redis veya benzeri bir önbellek kullanılıyor mu?
Dağıtık sistemlerde paylaşımlı rate limiting var mı?
D. Hata Yönetimi:
Rate limit aşıldığında 429 status kodu dönüyor mu?
Retry-After header'ı dönüyor mu?
Rate limit header'ları (X-RateLimit-*) dönüyor mu?
E. İzleme ve Log:
Rate limit aşımları loglanıyor mu?
Anormal yüksek trafik izleniyor mu?
Alert mekanizması var mı?
Özel Senaryolar:
1. Dağıtık Sistemlerde Rate Limiting
Redis Cluster kullanarak merkezi rate limiting.
Consul veya etcd ile dağıtık rate limiting.
python
import redis
from redis import RedisCluster
# Redis Cluster ile rate limiting
redis_client = RedisCluster(
host='redis-cluster',
port=6379,
decode_responses=True
)
2. Graceful Degradation
Rate limit aşıldığında tüm istekleri reddetmek yerine, esnek davranın.
python
def adaptive_rate_limit(request):
current_load = get_system_load()
if current_load < 50:
limit = 100
elif current_load < 75:
limit = 50
else:
limit = 10
# Limit'e göre rate limiting uygula
return check_rate_limit(request, limit)
3. Client Bazlı Rate Limiting
API anahtarları veya OAuth scope'ları bazlı farklı limitler.
python
def get_client_limit(api_key):
# Veritabanından veya cache'den client limit'ini al
client = Client.objects.get(api_key=api_key)
return client.rate_limit
🔒 Bu içeriği görmek için giriş yapın