System Design

Oran Sınırlamayı Ustalıkla Yönetmek: Dayanıklı ve Ölçeklenebilir Sistemler Mimarisi

Modern dağıtık sistemler dünyasında, kullanılabilirlik ve güvenilirliği sağlamak hayati önem taşır. Sistem mimarilerinin karşılaştığı sayısız zorluk arasında, hizmetleri kötüye kullanımdan, trafik artışlarından ve Hizmet Reddi (DoS) saldırılarından korumak öne çıkar. Oran sınırlama, kaynak tüketimini yönetmek ve sistemin olumsuz koşullar altında performansını korumasını sağlamak için temel stratejidir. Bu yazıda, sistem tasarımında oran sınırlamanın temel kavramları, algoritmaları ve pratik uygulamaları ele alınmaktadır.

Neden Oran Sınırlama Önemlidir?

Oran sınırlama yalnızca bir güvenlik önlemi değildir; aynı zamanda hizmet kalitesi mekanizmasıdır. Bunun olmaması durumunda, tek bir kötü davranan istemci veya viral bir trafik artışı, CPU, bellek veya veritabanı bağlantılarını tüketerek tüm kullanıcılar için performansı düşürebilir. Bir istemcinin belirli bir zaman diliminde yapabileceği istek sayısını sınırlayarak şunları sağlarsınız:

  • Kötüye Kullanımı Önleyin: Kötü niyetli aktörlerin veri kazımasını veya şifre kırma (brute-force) saldırılarını durdurun.
  • Adilliği Sağlayın: Tek bir kullanıcının sistem kaynaklarını tek başına ele geçirmesini engelleyin.
  • Maliyetleri Yönetin: Hesaplama yükünü sınırlayın; bu, sunucusuz (serverless) veya kullanım başına ödeme mimarileri için hayati önem taşır.
  • Kademeli Bozulma Sağlayın: Sistem çökmesine neden olmak yerine anlamlı hatalar (örneğin HTTP 429 Çok Fazla İstek) döndürün.

Yaygın Oran Sınırlama Algoritmaları

Doğru algoritmanın seçimi, trafik desenlerinize ve dalgalanmalara (burstiness) olan toleransınıza bağlıdır. En yaygın üç yaklaşım Sabit Pencere Sayacı, Kayan Pencere Günlüğü ve Token Havuzu'dur.

Sabit Pencere Sayacı uygulanması en basit olanıdır ancak "sınır problemi"nden muzdariptir; bir pencerenin sonunda ve bir sonrakine başlangıçta izin verilen istekler, limiti iki katına kadar aşabilir. Daha pürüzsüz bir kontrol için Kayan Pencere Günlüğü, her istek zaman damgasını izleyerek daha yüksek bellek kullanım pahasına hassasiyet sunar. Ancak Token Havuzu algoritması, sadelik ve esneklik dengesinden dolayı genellikle tercih edilen seçenektir. Kısa süreli trafik artımlarına izin verirken uzun vadeli ortalama bir hızı korur; bu da değişken yükleri yönetmesi gereken API'ler için idealdir.

Redis ile Token Havuzu Uygulaması

Dağıtık bir ortamda paylaşılan durum (state) kritik öneme sahiptir. Redis, hızı ve atomik işlemleri sayesinde dağıtık oran sınırlama uygulamaları için de facto standarttır. Aşağıda, temel bir token havuzu mantığını uygulamak için redis-py kütüphanesini kullanan bir Python örneği bulunmaktadır.

import time
import redis

class RateLimiter:
    def __init__(self, redis_client, rate, capacity):
        self.redis = redis_client
        self.rate = rate       # Saniye başına eklenen token sayısı
        self.capacity = capacity # İzin verilen maksimum token sayısı
        self.tokens_key = "rate_limit:"

    def is_allowed(self, client_id):
        key = f"{self.tokens_key}{client_id}"
        now = time.time()
        
        # Mevcut token sayısını ve son güncelleme zamanını alın
        pipe = self.redis.pipeline()
        pipe.get(key)
        pipe.execute()
        
        # Anahtar yoksa başlatın
        data = self.redis.get(key)
        if data is None:
            self.redis.set(key, self.capacity)
            self.redis.expire(key, 60) # Temizlik için 60 saniye sonra süresi dolması
            return True
            
        current_tokens = float(data)
        
        # Geçen süreye göre yeni tokenlar ekleyin
        time_passed = time.time() - (self.redis.get(f"{key}:last_access") or now)
        new_tokens = min(self.capacity, current_tokens + (time_passed * self.rate))
        
        if new_tokens >= 1:
            self.redis.set(key, new_tokens - 1)
            self.redis.set(f"{key}:last_access", now)
            return True
        else:
            self.redis.set(key, new_tokens)
            self.redis.set(f"{key}:last_access", now)
            return False

Pratik Dikkat Edilmesi Gerekenler

Oran sınırlama uygularken limiti nerede uygulayacağınızı düşünün. Ağ geçidi seviyesinde oran sınırlama (Nginx, Kong veya AWS API Gateway kullanarak), kötü trafiğin uygulama sunucularınıza ulaşmadan engellenmesi açısından verimlidir. Ancak uygulama seviyesinde sınırlama, ücretsiz ve ücretli kullanıcılar için katmanlı limitler gibi daha ince granüllü iş mantığına olanak tanır.

Limitleri her zaman net bir şekilde iletişim kurun. API tüketicilerinin kullanımını anlamalarına yardımcı olmak için X-RateLimit-Limit, X-RateLimit-Remaining ve X-RateLimit-Reset gibi standart HTTP başlıklarını kullanın. Ayrıca, istemcilerin ne zaman yeniden deneme yapması gerektiğini bilmelerini sağlamak için hata yanıtlarınızın bir Retry-After başlığı içerdiğinden emin olun.

Sonuç

Oran sınırlama, sağlam sistem tasarımının temel bir bileşenidir. Farklı algoritmalar arasındaki ödemeler (trade-offs) konusunda bilgi sahibi olarak ve dağıtık durum yönetimi için Redis gibi araçlardan yararlanarak, dayanıklı, adil ve güvenli sistemler oluşturabilirsiniz. Uygulamanız büyüdükçe, oran sınırlama stratejilerinizi düzenli olarak gözden geçirin; böylece bunların gelişen trafik desenleriniz ve iş hedeflerinizle uyumlu olduğundan emin olursunuz.

Share: