ホームページ > バックエンド開発 > Golang > 初心者向けのレート制限: その概要と Go でレート制限を構築する方法

初心者向けのレート制限: その概要と Go でレート制限を構築する方法

Barbara Streisand
リリース: 2025-01-01 07:58:10
オリジナル
627 人が閲覧しました

レート制限は、Web 開発および API 設計における重要な概念です。これにより、ユーザーまたはシステムが特定の時間枠内でサーバーに対して限られた数のリクエストのみを実行できるようになります。このブログ投稿では、レート制限とは何か、なぜそれが不可欠なのか、Go でシンプルなレート制限を実装する方法について説明します。

Rate Limiting for Beginners: What It Is and How to Build One in Go

レート制限とは何ですか?

10 分ごとに 10 人しか収容できないジェット コースターがあるテーマパークを想像してください。時間内に 10 人を超える人が乗車しようとすると、待たなければなりません。この類似性は、ソフトウェア システムにおけるレート制限の原理を反映しています。

技術用語では、レート制限は、クライアント (ユーザー、デバイス、IP アドレスなど) が事前定義された期間内にサーバーに送信できるリクエストの数を制限します。役に立ちます:

  1. 乱用を防止し、リソースの公正な使用を確保します。
  2. 過剰なトラフィックによる過剰な負荷からサーバーを保護します。
  3. コストのかかるサードパーティの API やサービスの過剰使用を避けてください。

たとえば、API ではユーザーごとに 1 分あたり 100 件のリクエストが許可される場合があります。ユーザーがこの制限を超えた場合、サーバーは制限がリセットされるまでそれ以上のリクエストを拒否します。

レート制限はどのように機能しますか?

レート制限を実装する一般的な方法の 1 つは、トークン バケット アルゴリズム を使用することです。仕組みは次のとおりです:

  1. バケットは、固定数のトークン (例: 10) から始まります。
  2. リクエストごとに、バケットから 1 つのトークンが削除されます。
  3. バケットにトークンが残っていない場合、リクエストは拒否されます。
  4. トークンは、バケットがいっぱいになるまで一定の速度 (例: 1 秒ごとに 1 トークン) で補充されます。

Go で単純なレート リミッターを構築する

各クライアントを 1 分あたり 3 つのリクエストに制限するレート リミッターを Go で構築してみましょう。

ステップ 1: レート リミッター構造を定義する

sync.Mutex を使用してスレッドの安全性を確保し、トークンの数、最大容量、補充率などの情報を保存します。

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(),
    }
}
ログイン後にコピー
ログイン後にコピー

ステップ 2: トークン補充ロジックを実装する

トークンは、最後の補充からの経過時間に基づいて定期的に補充する必要があります。

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
}
ログイン後にコピー
ログイン後にコピー

ステップ 3: リクエストが許可されているかどうかを確認する

Allow メソッドは、使用可能なトークンに基づいてリクエストを続行できるかどうかを決定します。

func (r *RateLimiter) Allow() bool {
    r.mutex.Lock()
    defer r.mutex.Unlock()

    r.refillTokens()

    if r.tokens >= 1 {
        r.tokens--
        return true
    }
    return false
}
ログイン後にコピー
ログイン後にコピー

ステップ 4: IP ごとにレート制限を適用する

クライアントごとのリクエストを制限するために、IP アドレスとそれぞれのレート リミッターのマップを作成します。

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
}
ログイン後にコピー

ステップ 5: レート制限用のミドルウェアを作成する

最後に、各クライアントにレート制限を適用する HTTP ミドルウェアを作成します。

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(),
    }
}
ログイン後にコピー
ログイン後にコピー

ステップ 6: サーバーをセットアップする

すべてを組み合わせてレート リミッターをテストする方法は次のとおりです。

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
}
ログイン後にコピー
ログイン後にコピー

レートリミッターのテスト

サーバーを起動し、curl またはブラウザを使用してテストします。

func (r *RateLimiter) Allow() bool {
    r.mutex.Lock()
    defer r.mutex.Unlock()

    r.refillTokens()

    if r.tokens >= 1 {
        r.tokens--
        return true
    }
    return false
}
ログイン後にコピー
ログイン後にコピー
  • 3 つのリクエストをすぐに送信します。すべて成功するはずです。
  • 同じ 1 分以内に 4 回目のリクエストを送信します。「レート制限を超えました」というメッセージが表示されます。
  • 20 秒待ってから再試行してください。バケットが補充され、リクエストは成功するはずです。

ソースコード

GitHub リポジトリ

以上が初心者向けのレート制限: その概要と Go でレート制限を構築する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート