インターネットとモバイル インターネットの急速な発展に伴い、サーバーへの負荷は増大しており、サーバーへのクライアント要求をどのように制限し、サーバーのクラッシュを回避するかが大きな問題となっています。実際のプロジェクトでは、Web サイトの可用性を確保するために、IP リクエストの数を制限する必要があることがよくあります。
ここでは、Golang を使用して IP 電流制限を実装する方法を紹介します。一般に、トークン バケット アルゴリズムを使用して、IP アドレスに基づいた電流制限を実装します。トークン バケット アルゴリズムは、一定期間内に一定数のリクエストの通過を許可し、一定期間内のリクエスト フローを制限するフロー制御アルゴリズムです。
実装の詳細
トークン バケット アルゴリズムは、一定のレートでトークンをバケットに入れます。トークン バケットには容量制限があります。つまり、バケット内のトークンの数が上限を超えないことを意味します。容量。リクエストごとにトークンがバケットから削除されます。バケットにトークンがない場合、リクエストは処理されません。
IP アドレスに基づいて電流制限を実装するには、IP アドレスごとに最大容量と一定速度のトークン バケットを作成する必要があります。リクエストが来ると、トークン バケットからトークンを削除し、バケットにトークンがない場合はリクエストを拒否します。
これに基づいて、IP 電流リミッターを定義できます。
type IPRateLimiter struct { limiterBuckets map[string]*rate.Limiter mu *sync.Mutex r rate.Limit b int }
その中で、limitterBuckets は文字列 IP アドレスをトークン バケットにマッピングするマッピングです。 mu はミューテックス、r はレート リミッターが 1 秒あたりにトークンを配置する速度、b はトークン バケットの容量です。
IP アドレスごとにトークン バケットを作成するために、関数 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 }
AddIP 関数を使用して、IP アドレスのトークン バケットを作成します。この IP アドレスに対してトークン バケットが作成された場合は既存のトークン バケットが返され、それ以外の場合は新しいトークン バケットが作成されて返されます。
最後に、IP アドレスへのリクエストの数を制限する HTTP ミドルウェアを実装できます。
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) }) }
このミドルウェアにより、指定されたレートと容量でリクエストを通過させることができます。リクエスト数が容量を超えると、HTTP エラー コード 429 (Too Many Requests) が返されます。
完全なコードは次のとおりです:
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) } }
この例では、1 秒あたり 10 個のトークンを許可し、バケット容量を 100 に制限します。これは、リミッターは 1 秒あたり最大 10 件のリクエストを処理できますが、同じ IP アドレスへのリクエストが 100 件に達すると失敗することを意味します。同時に、「ようこそ」に応答する単純なハンドラーを定義します。
結論
この記事では、Golang を使用して IP 電流制限を実装し、トークン バケット アルゴリズムを使用して各 IP アドレスのリクエスト レートを制限します。この方法は、シンプルで効果的な電流制限メカニズムを実装でき、Golang で簡単に実装できます。これは、同時実行性の高いネットワーク アプリケーションを作成する場合に非常に役立つテクニックとなります。
以上がGolang は IP 電流制限を実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。