golang,go,博客,开源,编程
在 Go(Golang)中,基于滑动窗口的 IP 限速器是一种精确且高效的限流策略,适用于需要细粒度流量控制的场景,如防止恶意攻击、限制 API 调用频率等。
滑动窗口算法通过在每次请求时计算过去固定时间窗口内的请求数量,实现对请求速率的限制。
与固定窗口算法相比,滑动窗口算法能更平滑地限制流量,避免突发请求集中在窗口边界的问题。
以下是几个在 Go 中实现滑动窗口 IP 限速器的开源项目:
该库实现了 Kong API 网关使用的可扩展滑动窗口限流算法,适用于分布式环境。
特点:
示例:
假设每分钟允许 100 次请求,在第 75 秒时,当前窗口内有 12 次请求,前一个窗口内有 86 次请求,则当前估算的请求数为:(GitHub)
count = 86 * ((60 - 15) / 60) + 12 = 86 * 0.75 + 12 = 76.5
如果 count
超过设定的阈值,则拒绝请求。(Go Packages)
该库使用 Redis 实现滑动窗口限流,支持按 IP、API 路径或用户标识进行限流。
特点:
配置示例:
{
"limitsIp": {
"limit": 20,
"window": 1200,
"unit": "seconds"
}
}
上述配置表示:每个 IP 在 1200 秒(20 分钟)内最多允许 20 次请求。
该库实现了基于 Redis 的分布式滑动窗口限流器,适用于需要高可用性的系统。
特点:
示例:
limiter, err := ratelimit.New(0, urlHash, 100, 60, 5, "localhost:6379")
上述代码创建了一个限流器,允许每 60 秒最多 100 次请求,时间精度为 5 秒。
以下是一个简单的滑动窗口 IP 限速器实现示例:
package main
import (
"net/http"
"sync"
"time"
)
type RateLimiter struct {
mu sync.Mutex
requests map[string][]time.Time
limit int
window time.Duration
}
func NewRateLimiter(limit int, window time.Duration) *RateLimiter {
return &RateLimiter{
requests: make(map[string][]time.Time),
limit: limit,
window: window,
}
}
func (rl *RateLimiter) Allow(ip string) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
windowStart := now.Add(-rl.window)
timestamps := rl.requests[ip]
// 移除过期的时间戳
var validTimestamps []time.Time
for _, t := range timestamps {
if t.After(windowStart) {
validTimestamps = append(validTimestamps, t)
}
}
if len(validTimestamps) >= rl.limit {
return false
}
// 添加当前时间戳
validTimestamps = append(validTimestamps, now)
rl.requests[ip] = validTimestamps
return true
}
func main() {
limiter := NewRateLimiter(100, time.Minute)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ip := r.RemoteAddr
if !limiter.Allow(ip) {
http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
return
}
w.Write([]byte("Hello, World!"))
})
http.ListenAndServe(":8080", nil)
}
上述代码创建了一个限流器,限制每个 IP 每分钟最多 100 次请求。
滑动窗口 IP 限速器在 Go 中的实现可以通过多种方式完成,选择合适的库或自行实现取决于具体需求。对于分布式系统,推荐使用支持 Redis 的库,如 senderista/sliding-window-rate-limiter
;对于本地应用,RussellLuo/slidingwindow
提供了高效的解决方案。
在实现时,应注意线程安全和性能优化,以确保限流器的稳定性和高效性。