Penghadan kadar ialah konsep kritikal dalam pembangunan web dan reka bentuk API. Ia memastikan bahawa pengguna atau sistem hanya boleh membuat permintaan yang terhad kepada pelayan dalam jangka masa tertentu. Dalam catatan blog ini, kami akan meneroka apakah pengehadan kadar, sebab ia penting dan cara melaksanakan pengehad kadar yang mudah dalam Go.
Bayangkan taman tema dengan menaiki roller coaster yang hanya boleh memuatkan 10 orang setiap 10 minit. Jika lebih daripada 10 orang cuba untuk meneruskan dalam tempoh masa itu, mereka perlu menunggu. Analogi ini mencerminkan prinsip pengehadan kadar dalam sistem perisian.
Dalam istilah teknikal, pengehadan kadar mengehadkan bilangan permintaan pelanggan (cth., pengguna, peranti atau alamat IP) boleh hantar ke pelayan dalam tempoh yang telah ditetapkan. Ia membantu:
Sebagai contoh, API mungkin membenarkan 100 permintaan seminit bagi setiap pengguna. Jika pengguna melebihi had ini, pelayan menafikan permintaan selanjutnya sehingga had ditetapkan semula.
Satu cara biasa untuk melaksanakan pengehadan kadar adalah melalui algoritma baldi token. Begini cara ia berfungsi:
Mari kita mendalami membina pengehad kadar dalam Go yang mengehadkan setiap pelanggan kepada 3 permintaan seminit.
Kami akan menggunakan penyegerakan.Mutex untuk memastikan keselamatan rangkaian dan menyimpan maklumat seperti bilangan token, kapasiti maksimum dan kadar isi semula.
package main import ( "sync" "time" ) type RateLimiter struct { tokens float64 // Current number of tokens maxTokens float64 // Maximum tokens allowed refillRate float64 // Tokens added per second lastRefillTime time.Time // Last time tokens were refilled mutex sync.Mutex } func NewRateLimiter(maxTokens, refillRate float64) *RateLimiter { return &RateLimiter{ tokens: maxTokens, maxTokens: maxTokens, refillRate: refillRate, lastRefillTime: time.Now(), } }
Token hendaklah diisi semula secara berkala berdasarkan masa yang berlalu sejak isian semula terakhir.
func (r *RateLimiter) refillTokens() { now := time.Now() duration := now.Sub(r.lastRefillTime).Seconds() tokensToAdd := duration * r.refillRate r.tokens += tokensToAdd if r.tokens > r.maxTokens { r.tokens = r.maxTokens } r.lastRefillTime = now }
Kaedah Allow akan menentukan sama ada permintaan boleh diteruskan berdasarkan token yang tersedia.
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
Untuk mengehadkan permintaan setiap pelanggan, kami akan membuat peta alamat IP kepada pengehad kadar masing-masing.
type IPRateLimiter struct { limiters map[string]*RateLimiter mutex sync.Mutex } func NewIPRateLimiter() *IPRateLimiter { return &IPRateLimiter{ limiters: make(map[string]*RateLimiter), } } func (i *IPRateLimiter) GetLimiter(ip string) *RateLimiter { i.mutex.Lock() defer i.mutex.Unlock() limiter, exists := i.limiters[ip] if !exists { // Allow 3 requests per minute limiter = NewRateLimiter(3, 0.05) i.limiters[ip] = limiter } return limiter }
Akhir sekali, kami akan mencipta perisian tengah HTTP yang menguatkuasakan had kadar untuk setiap pelanggan.
package main import ( "sync" "time" ) type RateLimiter struct { tokens float64 // Current number of tokens maxTokens float64 // Maximum tokens allowed refillRate float64 // Tokens added per second lastRefillTime time.Time // Last time tokens were refilled mutex sync.Mutex } func NewRateLimiter(maxTokens, refillRate float64) *RateLimiter { return &RateLimiter{ tokens: maxTokens, maxTokens: maxTokens, refillRate: refillRate, lastRefillTime: time.Now(), } }
Berikut ialah cara menyambung semuanya dan menguji pengehad kadar.
func (r *RateLimiter) refillTokens() { now := time.Now() duration := now.Sub(r.lastRefillTime).Seconds() tokensToAdd := duration * r.refillRate r.tokens += tokensToAdd if r.tokens > r.maxTokens { r.tokens = r.maxTokens } r.lastRefillTime = now }
Mulakan pelayan dan ujinya menggunakan curl atau penyemak imbas anda:
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
Repo GitHub
Atas ialah kandungan terperinci Pengehadan Kadar untuk Pemula: Apa Itu dan Cara Membina Satu dalam Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!