Bu makale şuna dayanmaktadır: Redis'in akım sınırlama sisteminin tasarımı esas olarak akım sınırlayıcı sistemdeki akım sınırlama stratejisinin tasarımından bahseder; uygulama açısından, algoritma Redis'e erişmek için simge kovası algoritmasını kullanır ve lua betiğini kullanır.
1. Konsept
Bilgisayar ağlarında, hız sınırlama, bir ağ arayüz denetleyicisi tarafından gönderilen veya alınan trafik oranını kontrol etmek için kullanılır ve DoS saldırılarını önlemek için kullanılır
Anladığım kadarıyla tercüme etmek için kullan: mevcut sınırlama sistem içindir Gelen ve giden trafik, gelen ve giden büyük trafiği önlemek için kontrol edilir, bu da yetersiz kaynaklara ve sistem kararsızlığına neden olur.
Mevcut sınırlama sistemi, kaynak erişimi için iki ana işlevi kontrol eden bir kontrol bileşenidir: Mevcut sınırlama stratejisi ve birleştirme stratejisi. Kaynaştırma stratejisi için, farklı sistemlerin farklı birleştirme stratejisi gereksinimleri vardır. Bazı sistemler doğrudan reddetmek ister, bazı sistemler sırada beklemek, bazı sistemler hizmet bozulması ister ve bazı sistemler kendi sigortalarını özelleştirir. Stratejileri tek tek sıralamak zordur, bu nedenle bu makale yalnızca mevcut sınırlama stratejisinin işlevi için ayrıntılı bir tasarım yapmaktadır.
karşısında Mevcut sınırlama sisteminde, hız eşiğini aşan talepleri bulma işlevi için iki temel kavram vardır: kaynaklar ve stratejiler.
Sigorta stratejisi: Hız eşiğini aşan talepler için işleme stratejisi, sektörde ana akım bir terim değil, kendi başıma anladığım bir terimdir.
2. Mevcut sınırlama algoritması
2.1, anlık eşzamanlı sayısını sınırlayın
Tanım: anlık eşzamanlı sayı, sistem tarafından aynı anda işlenen istek / işlem sayısı
Avantajlar: Bu algoritma, eşzamanlı sayıları kontrol etme etkisine ulaşabilir.
Dezavantajlar: Kullanım senaryosu nispeten tektir ve genellikle gelen trafiği kontrol etmek için kullanılır
Java sözde kod uygulaması:
AtomicInteger atomic = new AtomicInteger (1) Deneyin { eğer (atomic.incrementAndGet () > Mevcut sınır) { // Sigorta mantığı } Başka { // Mantık işleme } } en sonunda { atomic.decrementAndGet (); }2.2, zaman penceresindeki maksimum istek sayısını sınırlayın
Tanım: zaman penceresindeki maksimum istek sayısı, belirtilen zaman aralığında izin verilen maksimum istek sayısı
Avantajlar: Bu algoritma, akış kontrol gereksinimlerinin çoğunu karşılayabilir ve maksimum QPS, zaman penceresindeki maksimum istek sayısından doğrudan dönüştürülebilir (QPS = istek sayısı / zaman penceresi)
Dezavantajlar: Bu şekilde, trafik düzgün olmayabilir ve zaman penceresindeki az miktarda trafik, özellikle büyük bir oranı oluşturur
Lua kodu uygulaması:
--- Özgün kaynak tanımlayıcı yerel anahtar = ANAHTARLAR --- Maksimum eşzamanlı zaman penceresi sayısı local max_window_concurrency = tonumber (ARGV) --- Zaman Penceresi yerel pencere = ton numarası (ARGV) --- Zaman penceresindeki mevcut eşzamanlı sayı local curr_window_concurrency = tonumber (redis.call ('get', key) veya 0) geçerli + 1 ise > o zaman sınırla yanlış dönmek Başka redis.call ("INCRBY", anahtar, 1) eğer pencere > -1 sonra redis.call ("sona erme", anahtar, pencere) son doğruya dön son2.3, jeton paketi
Algoritma Açıklaması
Öznitellikler
Avantajlar: Trafik nispeten akıcıdır ve belirli trafik patlamalarına dayanabilir
Mevcut sınırlama sistemimizin uygulaması jeton grubu algoritmasına dayandığından, özel kod uygulaması için aşağıdakilere bakın.
3. Proje gerçekleştirme
3.1. Teknik seçim
Not: Redis'i şu şekilde konumlandırdığımız için: önbellek, bilgi işlem ortamı, meta veriler db'de saklanır
3.2, mimari diyagramı
3.3, veri yapısı
Alan Açıklama Ad jetonu grubu uygulamalarının benzersiz tanımlaması, jeton paketinin uygulama listesini kullanabilir max_permits jeton paketi oranındaki maksimum jeton sayısını, Oluşturucu tarafından güncellenen kişi tarafından oluşturulan jeton paketine eklenme oranı
Mevcut sınırlama sisteminin uygulanması, uygulamayla hiçbir ilgisi olmayan redis'e dayanmaktadır, ancak mevcut sınırlayıcı meta veri yapılandırmasının birleşik yönetimini uygulama boyutu yönetimi ve kullanımı ile yapmak için, veri yapısı eklenir. Uygulamalar alanında bir sorun varsa, sorunu gidermek daha uygundur.
3.4, kod uygulaması
3.4.1 Kod uygulamasında karşılaşılan sorunlar
Jeton paketinin algoritma açıklamasına bakın. Genel fikir, RateLimiter istemcisine tekrarlayan bir iş parçacığı koymaktır. İş parçacığı, yapılandırmaya göre jeton grubuna jetonlar ekler. Bu uygulamanın aşağıdaki dezavantajları vardır:
3.4.2, çözüm
Yukarıdaki eksikliklere dayanarak, Google'ın guava'sında RateLimiter uygulamasına atıfta bulunarak, token eklemek için tetikleme yöntemini kullanıyoruz.
Algoritma Açıklaması
3.4.3, Lua kodu uygulaması
--- Token Al --- Dönüş kodu --- 0 Jeton paketi yapılandırması yok --- -1, jetonun alınamaması, yani pakette jeton olmadığı anlamına gelir --- 1, jetonu başarıyla almak anlamına gelir --- @param key Belirtecin (kaynak) benzersiz tanımlayıcısı --- @param, jeton miktarının talep edilmesine izin verir --- @param curr_mill_second geçerli milisaniye --- @param bağlamı Belirteç kullanan Uygulama Kimliği yerel işlev edinme (anahtar, izinler, curr_mill_second, bağlam) local rate_limit_info = redis.pcall ("HMGET", anahtar, "last_mill_second", "curr_permits", "max_permits", "rate", "uygulamalar") yerel last_mill_second = rate_limit_info local curr_permits = tonumber (rate_limit_info) local max_permits = tonumber (rate_limit_info) yerel oran = rate_limit_info yerel uygulamalar = rate_limit_info --- Hiçbir jeton paketinin yapılandırılmadığını belirtir tür (uygulamalar) == 'boolean' veya uygulamalar == nil veya içermiyorsa (uygulamalar, bağlam) o zaman dönüş 0 son local local_curr_permits = max_permits; --- Jeton paketi yeni oluşturuldu ve son jeton ediniminden bu yana geçen milisaniye sayısı boştu --- Jetonun pakete en son eklendiği saat ile mevcut saat arasındaki farka göre pakete jeton ekleyin --- Ve jeton pakete en son eklendiğinde güncelleme --- Pakete eklenen jeton sayısı birden azsa jetonun pakete en son eklendiği zaman güncellenmez eğer ((last_mill_second) ~ = 'boolean' ve last_mill_second ~ = false ve last_mill_second ~ = nil yazın) ise yerel ters_permits = math.floor (((curr_mill_second-last_mill_second) / 1000) * oran) yerel beklenen_ izinler = ters_izinler + geçerli izinler; local_curr_permits = math.min (beklenen_curr_permits, max_permits); --- 0'dan büyük olması, ilk kez bir jeton almanın olmadığı ve pakete jeton eklenmediği anlamına gelir eğer (ters_izinler > 0) sonra redis.pcall ("HSET", anahtar, "last_mill_second", curr_mill_second) son Başka redis.pcall ("HSET", anahtar, "last_mill_second", curr_mill_second) son yerel sonuç = -1 eğer (local_curr_permits-permits > = 0) sonra sonuç = 1 redis.pcall ("HSET", anahtar, "curr_permits", local_curr_permits-permits) Başka redis.pcall ("HSET", anahtar, "curr_permits", local_curr_permits) son dönüş sonucu sonMevcut sınırlama sisteminin tüm uygulama ayrıntılarıyla ilgili olarak, onu github'a, gitbub adresine koydum: ilgilenen öğrenciler, yazarın sınırlı deneyimi ve bilgisi nedeniyle, koddaki herhangi bir hata veya önyargıyı tartışabilir ve düzeltebilir.
3.4.4, yönetim arayüzü
Önceki tasarımda, mevcut sınırlayıcı konfigürasyon uygulama ile ilgilidir. Konfigürasyonu daha iyi yönetmek için, konfigürasyonu kontrol etmek için birleşik bir yönetim sayfasına ihtiyaç vardır:
3.5, performans testi
Yapılandırma: aws-Elasticcache-redis 2 core 4g
Ratelimiter-client'ın işlevi nispeten basit olduğundan, temelde redis performansında bir indirimdir.
4. Özet
Mevcut sınırlama sistemi, tasarımdan uygulamaya göre nispeten basittir, ancak gerçekten çok pratiktir. Dört kelimeyle tanımlanabilir: Kısa ve güçlü, daha önemli olan şey şirketin yetki sistemini ve sistem yapısını birleştirerek şirketin spesifikasyonlarını karşılayan mevcut bir sınırlama sistemi tasarlamaktır.
yetersiz: