Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: Laravel RateLimiter ve bir yarış durumu
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » Laravel RateLimiter ve bir yarış durumu

Yazılım

Laravel RateLimiter ve bir yarış durumu

teknomers
Son güncelleme: 14 Mayıs 2026 17:09
teknomers
Paylaş
Paylaş

Laravel belgelerinde gösterilen manuel rate-limiting örneklerinden biri ( Manually Incrementing Attempts bölümünde) şu şekildedir:

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $maxAttempts = 5)) {
    return 'Too many attempts!';
}

RateLimiter::increment('send-message:'.$user->id);

// Send message...

Yukarıdaki kod sorunsuz çalışabilir. Ancak biri saniyede 5 istekle sınırlı bir endpoint’e 100 eş zamanlı istek gönderirse, tüm 100 istek geçer.

Bu yarış durumu, captchaapi.eu, bir Proof-of-Work (PoW) CAPTCHA API’si inşa ederken başıma geldi. Bu konuda @_newtonjob’a teşekkür ederim, çünkü bunu 280 karakterde harika bir şekilde özetlemiş:

Rate limiting mantığınız, sınırlı olmalı olan bir endpoint’e 100 eş zamanlı istek gönderildiğinde işler. Çözüm: RateLimiter::hit() tarafından döndürülen artırılmış sayıyı kontrol edin ve bunun maksimum deneme sayısını aşmadığından emin olun.

Burada bir sorun var: Kurulum şekli, bir adet düzeltme ve çıkardığım dersler ile bu durumu açıklayacağım.


Neden bir sorun?

Tek bir isteği değerlendirelim:

  1. tooManyAttempts() mevcut sayıyı cache’den okur.
  2. Bu sayıyı $maxAttempts ile karşılaştırır.
  3. true veya false döner.
  4. Eğer false ise, kod increment() fonksiyonunu çağırarak sayıyı artırır.

Bu, iki bağımsız cache çağrısıdır. İlk ve son adım arasında, başka bir isteğin aynı güncel değeri okuma ihtimali vardır ve bu da kontrolü geçip artırma işlemi yapma penceresi yaratır.

100 eş zamanlı istekte bu durum ölçeklenerek gerçekleşir:

  • İstek 1 sayıyı 0 olarak okuyup kontrolü geçer (0 -> 1)
  • İstek 2 de aynı anda 0 sayısını okur, kontrolü geçer ve increment() çağrılır (0 -> 2)
  • …böyle devam eder ve 100’e kadar çıkar.

Sonuçta sayaç 100 olur, ama bunun üzerinden 100 istek zaten gerçekleşmiştir ve backend’iniz istediğiniz kadar işin 100 katını işlemiştir. Eğer endpoint ağır bir işlem (bir PoW zorluğu, AI işlemesi, dış API çağrısı) yapıyorsa, 5 yerine 100 işlemlik bir ücret ödemiş olursunuz.


Neden artırma atomiktir ama kontrol değil?

Laravel kaynak kodunu açtığınızda (Illuminate\Cache\RateLimiter::increment() 12.x’te):

public function increment($key, $decaySeconds = 60, $amount = 1)
{
    $key = $this->cleanRateLimiterKey($key);

    $this->cache->add(
        $key.':timer', $this->availableAt$decaySeconds), $decaySeconds
    );

    $added = $this->withoutSerializationOrCompression(
        fn () => $this->cache->add($key, 0, $decaySeconds)
    );

    $hits = (int) $this->cache->increment($key, $amount);

    // ...

    return $hits;
}

Ve hit() de tam olarak increment() ile aynıdır:

public function hit($key, $decaySeconds = 60)
{
    return $this->increment($key, $decaySeconds);
}

Buradaki önemli nokta: $this->cache->increment($key, $amount) bir atomik işlemdir.

captchaapi.eu’da Redis kullanıyorum, burada bu INCR (veya INCRBY) komutları ile eşleşir ve Redis’in en eski ve en sağlam komutlarından biridir. Tek anahtar yazımı düzeyinde atomiktir: iki eş zamanlı istek aynı değeri okuyamaz ve her biri benzersiz artan sonuca sahiptir. Memcached de aynı garantileri sağlayan bir incr komutuna sahiptir.

Buradaki önemli şey: increment() artıştan sonraki sayıyı döner. Dönen değer atomik, belirleyici ve her eş zamanlı çağırıcı için benzersizdir.

$hits = RateLimiter::increment($key);
// 100 eş zamanlı istekte geri dönüş değerleri 1, 2, 3, ..., 100 olarak elde edilir
// (rastgele sırada, ama her değer tamı tamına bir kez)

Diğer yandan, tooManyAttempts() ayrı bir okuma işlemidir. Güncel olmayan bir değer dönebilir ve bu okuma işlemi ile sonraki yazma işlemi arasındaki boşluk sizin yarış pencerenizi ortaya çıkarır.


Çözüm: Tek artış, dönüş değerini kontrol et

İki adımlı desenin gereğini ( tooManyAttempts → increment) bırakın ve tek bir çağrı yapın:

$attempts = RateLimiter::increment('send-message:'.$user->id);

if ($attempts > $maxAttempts) {
    return 'Too many attempts!';
}

// Mesajı gönder...

Artık 100 eş zamanlı istekle:

  • Her istek artıştan sonra benzersiz bir sayıya ulaşır.
  • İlk 5 istek 1-5 değerlerini alır ve geçer.
  • Kalan 95 istek 6-100 değerlerini alır ve reddedilir.

Artık pencere yok, yarış durumu yok. Redis’in atomik artışı tek gerçeklik kaynağıdır ve increment() size bu gerçeği doğrudan sağlar.

Belirtmek gereken ince bir ayrıntı: orijinal desende, artış kontrol sonrası gerçekleşir, bu nedenle herhangi bir aşım sayıda kalır (“sayacın 6 göstermesi ancak 6. isteğe izin vermek istemek”). Yeni desende her seferinde artış yapıyorsunuz ve dönüş değerini kontrol ediyorsunuz; bu nedenle sayaç 100 gösterebilir. Bu da sorun değildir çünkü limitin üzerindeki her şey reddedildi. Sayaç gösterimi aynı zamanı işaret edebilir, ancak güvenlik modeli daha sıkıdır.


hit() ve increment(): hangisini seçmeli?

İkisi de aynı şeyi yapar. hit() tam olarak function hit($key, $decay) { return $this->increment($key, $decay); } şeklindedir. Mevcut Laravel belgeleri (10.x ve üzeri) örneklerinde increment() kullanıyor; daha eski versiyonlar (8.x, 9.x) hit() kullanıyordu. İkisi de çalışır, hangisi daha doğal geliyorsa onu seçin:

  • hit(): “bir olayı kaydet” mantığı, rate limiting ile doğal bir uyum sağlar.
  • increment(): atomik sayaç yönüne veya amount: parametresi ile birden fazla artırmayı vurgulamak istediğinizde tercih edin.

captchaapi.eu’da increment() kullanmayı tercih ettim, çünkü güncel belgelerle eşleşiyor ve dönüş değerine önem verdiğimi açıkça gösteriyor.


Bu durum nerede işe yaramaz?

Bunun bazı açık sınırlamaları var: bu, sadece tek bir Redis örneğinde gerçekleşen yarışları korur (ya da Redis kümesinde, yani her anahtarın bir parçacığın üzerinde yaşadığı durumda). Eğer Redis’i bölgeler arasında koordine olmadan böler ve bir saldırgan her bölgede istekler başlatırsa, INCR atomikliği size yardımcı olamaz. Her bölgede 100 istek alırsınız, N bölgesi kadar.

captchaapi.eu’da bu yeterlidir çünkü tüm uygulama tek bir Redis’e (Hetzner Nuremberg) karşı çalışır. Çok bölgeli dağıtılmış rate limiting için kaydeden bir log veya merkezi bir bilgi kaynağı ile token bucket gibi bir yapı gereklidir. Farklı bir konudur.

Bir diğer limit: bu, sayaç düzeyindeki yarışlar için bir düzeltmedir. Bir saldırgan IP’lerini değiştirirse (botnet, konut proxy’si), herhangi bir IP bazlı rate limit bunu engelleyemez. Bu farklı bir sorundur ve captchaapi.eu’da bunu PoW zorluğu ile ele alıyorum.

Bir şey daha açıkça belirtmek gerekirse: HTTP rotaları için Laravel’daki önerilen yol throttle middleware kullanmaktır, manuel rate-limiting kodu değil. Bu gönderi, manuel desensiz üzerinde duruyor, bu da rate-limiting’i HTTP dışı işlemler, bir kontrolördeki özelleştirilmiş mantık ya da throttle middleware’nin uygun olmadığı herhangi bir şey için başvurduğunuzdeseni anlatıyor.


Çıkardığım dersler

Küçük bir düzeltme, ancak benim için bazı şeyler yeni anlam kazandı.

1. “Çalışıyor” ile “güvenli” aynı şey değildir. Üzerinde belgelenmiş manuel desenle üretimde bir süre çalıştım ve bir hata görmedim, çünkü captchaapi.eu’ya hiç saldırgan gelmedi. Bu yarışlar sessizdir. Uygulama logları hiç bir şey söylemez, izleme yeşil gösterir ve limitlerin aslında tutulmadığını ancak biri wrk -c 100 ile geldiğinde öğrenirsiniz. Artık pahalı bir işlem için rate-limiting kodunu gözden geçirdiğimde, başlayarak: “100 isteğin aynı mikrosaniyede gelmesi durumunda ne olur?” diye düşünüyorum.

2. Atomik işlemlerden dönen değer, yazmam gereken kod değil. Redis, her atomik artışla sizin için benzersiz bir sıra numarası verir. Reddetmek için kullanabilirsiniz, ancak başka iş mantıkları için de kullanabilirsiniz, aksi takdirde daha fazla kod ve kilit ile çözülecek bir durumdur. tooManyAttempts() kullanıp increment()‘ın dönüş değerini görmezden gelmek, Redis’in zaten size verdiği bilgiyi fırlatmak demektir.

3. Belgelenmiş manuel desen her zaman en güvenlisi değildir. Laravel belgelerinde tooManyAttempts() + increment() (veya eski versiyonlarda hit()) “Manually Incrementing Attempts” başlığı altında gösterilmektedir. Hatalı değil, çoğu kullanım için (kullanıcı başına limitler, kullanıcıların 100 eş zamanlı istekte bulunmaması durumunda) yeterlidir. Ama eğer paralel istismar tehdidi oluşturuyorsanız, belgeler en güvenli seçeneği göstermiyor. Şimdi belgeleri biraz farklı okuyorum: “Buradaki varsayılan kullanıcı kimdir ve tehdit modeli benimle uyumlu mu?”

4. X, güvenlik konularını topladığım yerdir. Bu özel düzeltme, belgeler veya bir güvenlik denetimi yerine, bir 280 karakterlik gönderi yoluyla ulaştı, bu yüzden Laravel kullanıcılarını takip etmek, gerçek uygulamalardaki belirli desen düzeyindeki hataları paylaşan, benim için çoğu güvenlik blogundan daha fazla bilgi sağlıyor. “X’in üstünde yaşadım, bunu böyle düzeltim” şeklinde yazan insanların tweetlerine mürekkep etmeye özen gösterin. Bu, kendi kodunuz için gereken desen eşleştirme türüdür. Teşekkürler, @_newtonjob.


TL;DR

// ❌ Yarışa açık — 100 eş zamanlı istek hepsi geçecektir
if (RateLimiter::tooManyAttempts($key, 5)) {
    return 'Too many!';
}
RateLimiter::increment($key);

// ✅ Yarışa güvenli — atomik artış + dönüş değerini kontrol et
if (RateLimiter::increment($key) > 5) {
    return 'Too many!';
}

Bir satır kısaltma, bir sorun ortadan kalktı. Eğer Laravel’deki tooManyAttempts() + increment() (veya hit()) çift adım desenini kullanan bir rate-limiting kodunuz varsa, bunu gözden geçirin ve tek çağrılı varyantı yeniden yazın. Özellikle her çağrı size bir şeyler kazandıran bir işlemi koruyorsanız.

Kaynak: Orijinal Makale

Contents
  • Neden bir sorun?
  • Neden artırma atomiktir ama kontrol değil?
  • Çözüm: Tek artış, dönüş değerini kontrol et
  • hit() ve increment(): hangisini seçmeli?
  • Bu durum nerede işe yaramaz?
  • Çıkardığım dersler
  • TL;DR
WhatsApp Medyasını Medya Kimliği Kullanarak İndirme ve Kaydetme (WhatsApp Cloud API) – Laravel ve Core PHP ile
PHP’ye Nasıl Başlanır? Yeni Başlayanlar için Basit Bir Rehber
Laravel Reverb’i Üretim Ortamında Nginx ile Nasıl Yapılandırılır
PHP 8 + RoadRunner: PHP Ekosisteminde Performans Optimizasyonu
MultiCarbon: PHP Carbon için Yerel Jalali ve Hicri Takvim Desteği
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale AMD’nin FSR 4.1 Yükseltme Teknolojisi Eski Grafik Kartlarına Geliyor
Sonraki Makale Klipsch The Fives II İncelemesi: Müzik ve Film İçin Ideal Mi?

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Acil: Cisco Catalyst SD-WAN Yöneticisi CVE-2026-20245 Açıkları Tehdit Ediyor
Siber Güvenlik
N++ Sonrası Yeni Oyun İçin Beklentiler ve Heyecan Durumu
Oyun
Laufey’in Savaş Taktiği Eski Yunan Üçlemesinden İlham Aldı
Oyun
Şimşek, coaxial kablodan apartmana girip PC’yi patlattı
Donanım
Outlook’un yıllardır güvenlik açığı, Fedora ve Dovecot güncellemesiyle ortaya çıktı
Donanım
Yaz Geliştirici Festivali 2026: Tüm Yenilikler Ortaya Çıkıyor
Oyun
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?