Golang implementiert eine IP-Strombegrenzung

王林
Freigeben: 2023-05-10 09:21:06
Original
655 Leute haben es durchsucht

Mit der rasanten Entwicklung des Internets und des mobilen Internets ist es zu einem großen Problem geworden, Client-Anfragen an den Server zu beschränken und Serverabstürze zu vermeiden. In tatsächlichen Projekten müssen wir häufig die Anzahl der IP-Anfragen begrenzen, um die Verfügbarkeit der Website sicherzustellen.

Hier stellen wir vor, wie man mit Golang eine IP-Strombegrenzung implementiert. Im Allgemeinen verwenden wir den Token-Bucket-Algorithmus, um eine Strombegrenzung basierend auf der IP-Adresse zu implementieren. Der Token-Bucket-Algorithmus ist ein Flusskontrollalgorithmus, der eine bestimmte Anzahl von Anforderungen innerhalb eines bestimmten Zeitraums passieren lässt und den Anforderungsfluss innerhalb eines bestimmten Zeitraums begrenzt.

Implementierungsdetails

Der Token-Bucket-Algorithmus legt Token mit einer konstanten Rate in den Bucket. Der Token-Bucket hat eine Kapazitätsgrenze, was bedeutet, dass die Anzahl der Token im Bucket die Kapazität nicht überschreitet. Für jede Anfrage wird ein Token aus dem Bucket entfernt. Wenn sich kein Token im Bucket befindet, kann die Anfrage nicht weitergeleitet werden.

Um eine Strombegrenzung basierend auf der IP-Adresse zu implementieren, müssen wir für jede IP-Adresse einen Token-Bucket erstellen. Jeder Token-Bucket hat eine maximale Kapazität und eine konstante Geschwindigkeit. Wenn eine Anfrage eingeht, entfernen wir ein Token aus dem Token-Bucket und lehnen die Anfrage ab, wenn sich kein Token im Bucket befindet.

Auf dieser Grundlage können wir einen aktuellen IP-Limiter definieren:

type IPRateLimiter struct {
    limiterBuckets map[string]*rate.Limiter
    mu             *sync.Mutex
    r              rate.Limit
    b              int
}
Nach dem Login kopieren

wobei limiterBuckets eine Zuordnung ist, die String-IP-Adressen Token-Buckets zuordnet. mu ist ein Mutex, r ist die Rate, mit der der Ratenbegrenzer Token pro Sekunde platziert, und b ist die Kapazität des Token-Buckets.

Um einen Token-Bucket für jede IP-Adresse zu erstellen, definieren wir eine Funktion NewIPRateLimiter:

func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
    return &IPRateLimiter{
        limiterBuckets: make(map[string]*rate.Limiter),
        mu:             &sync.Mutex{},
        r:              r,
        b:              b,
    }
}

func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
    i.mu.Lock()
    defer i.mu.Unlock()

    limiter := rate.NewLimiter(i.r, i.b)
    i.limiterBuckets[ip] = limiter

    return limiter
}
Nach dem Login kopieren

Die AddIP-Funktion wird verwendet, um einen Token-Bucket für eine IP-Adresse zu erstellen. Wenn für diese IP-Adresse ein Token-Bucket erstellt wurde, wird der vorhandene Token-Bucket zurückgegeben, andernfalls wird ein neuer Token-Bucket erstellt und zurückgegeben.

Schließlich können wir HTTP-Middleware implementieren, um die Anzahl der Anfragen an eine IP-Adresse zu begrenzen:

func (i *IPRateLimiter) Limit(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.RemoteAddr
        limiter, ok := i.limiterBuckets[ip]
        if !ok {
            limiter = i.AddIP(ip)
        }

        if !limiter.Allow() {
            http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}
Nach dem Login kopieren

Diese Middleware ermöglicht die Weiterleitung von Anfragen mit einer bestimmten Geschwindigkeit und Kapazität. Wenn die Anzahl der Anfragen die Kapazität überschreitet, wird der HTTP-Fehlercode 429 (Too Many Requests) zurückgegeben.

Der vollständige Code lautet wie folgt:

package main

import (
    "net/http"
    "strconv"
    "sync"

    "golang.org/x/time/rate"
)

type IPRateLimiter struct {
    limiterBuckets map[string]*rate.Limiter
    mu             *sync.Mutex
    r              rate.Limit
    b              int
}

func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
    return &IPRateLimiter{
        limiterBuckets: make(map[string]*rate.Limiter),
        mu:             &sync.Mutex{},
        r:              r,
        b:              b,
    }
}

func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
    i.mu.Lock()
    defer i.mu.Unlock()

    limiter := rate.NewLimiter(i.r, i.b)
    i.limiterBuckets[ip] = limiter

    return limiter
}

func (i *IPRateLimiter) Limit(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.RemoteAddr
        limiter, ok := i.limiterBuckets[ip]
        if !ok {
            limiter = i.AddIP(ip)
        }

        if !limiter.Allow() {
            http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("welcome."))
}

func main() {
    limit := rate.Limit(10) // 速率,每秒放入令牌的数量
    capacity := 100        // 容量,桶的大小

    ipRateLimiter := NewIPRateLimiter(limit, capacity)

    http.Handle("/", ipRateLimiter.Limit(http.HandlerFunc(IndexHandler)))

    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
}
Nach dem Login kopieren

In diesem Beispiel erlauben wir 10 Token pro Sekunde und begrenzen die Bucket-Kapazität auf 100. Das bedeutet, dass der Limiter bis zu 10 Anfragen pro Sekunde verarbeiten kann, jedoch fehlschlägt, wenn die Anfragen an dieselbe IP-Adresse 100 erreichen. Gleichzeitig definieren wir einen einfachen Handler, der auf „Willkommen“ antwortet.

Fazit

In diesem Artikel haben wir Golang verwendet, um die IP-Strombegrenzung zu implementieren, indem wir den Token-Bucket-Algorithmus verwendet haben, um die Anforderungsrate jeder IP-Adresse zu begrenzen. Diese Methode kann einen einfachen und effektiven Strombegrenzungsmechanismus implementieren und kann problemlos in Golang implementiert werden. Dies kann eine sehr nützliche Technik sein, wenn Sie hochgradig gleichzeitige Netzwerkanwendungen schreiben.

Das obige ist der detaillierte Inhalt vonGolang implementiert eine IP-Strombegrenzung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!