La limitation de débit est un concept essentiel dans le développement Web et la conception d'API. Cela garantit que les utilisateurs ou les systèmes ne peuvent envoyer qu'un nombre limité de requêtes à un serveur dans un laps de temps spécifique. Dans cet article de blog, nous explorerons ce qu'est la limitation de débit, pourquoi elle est essentielle et comment implémenter un limiteur de débit simple dans Go.
Imaginez un parc à thème avec des montagnes russes qui ne peuvent accueillir que 10 personnes toutes les 10 minutes. Si plus de 10 personnes tentent de s’inscrire dans ce délai, elles devront attendre. Cette analogie reflète le principe de limitation de débit dans les systèmes logiciels.
En termes techniques, la limitation de débit restreint le nombre de requêtes qu'un client (par exemple, un utilisateur, un appareil ou une adresse IP) peut envoyer à un serveur au cours d'une période prédéfinie. Ça aide :
Par exemple, une API peut autoriser 100 requêtes par minute et par utilisateur. Si un utilisateur dépasse cette limite, le serveur refuse toute demande supplémentaire jusqu'à ce que la limite soit réinitialisée.
Un moyen courant de mettre en œuvre une limitation de débit consiste à utiliser l'algorithme de compartiment de jetons. Voici comment cela fonctionne :
Plongeons dans la création d'un limiteur de débit dans Go qui limite chaque client à 3 requêtes par minute.
Nous utiliserons sync.Mutex pour garantir la sécurité des threads et stocker des informations telles que le nombre de jetons, la capacité maximale et le taux de recharge.
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(), } }
Les jetons doivent être réapprovisionnés périodiquement en fonction du temps écoulé depuis la dernière recharge.
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 }
La méthode Allow déterminera si une demande peut être traitée en fonction des jetons disponibles.
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
Pour limiter les requêtes par client, nous créerons une carte des adresses IP avec leurs limiteurs de débit respectifs.
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 }
Enfin, nous créerons un middleware HTTP qui applique la limite de débit pour chaque client.
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(), } }
Voici comment tout connecter ensemble et tester le limiteur de débit.
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 }
Démarrez le serveur et testez-le en utilisant curl ou votre navigateur :
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
Dépôt GitHub
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!