Go 语言实现
Go 语言中的实用速率限制
1. 标准库方法
使用 time.Ticker 进行基本速率限制
func rateLimitedFunction() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// 处理请求
performAction()
}
}
}
2. 高级速率限制包
创建一个全面的速率限制器
type RateLimiter struct {
mu sync.Mutex
limit rate.Limit
burst int
limiter *rate.Limiter
}
func NewRateLimiter(requestsPerSecond float64, burstSize int) *RateLimiter {
return &RateLimiter{
limit: rate.Limit(requestsPerSecond),
burst: burstSize,
limiter: rate.NewLimiter(rate.Limit(requestsPerSecond), burstSize),
}
}
func (rl *RateLimiter) Allow() bool {
return rl.limiter.Allow()
}
3. 分布式速率限制
基于 Redis 的分布式速率限制器
type RedisRateLimiter struct {
client *redis.Client
keyPrefix string
limit int
window time.Duration
}
func (r *RedisRateLimiter) IsAllowed(key string) bool {
currentTime := time.Now()
key = fmt.Sprintf("%s:%s", r.keyPrefix, key)
// 原子递增并检查
result, err := r.client.Eval(`
local current = redis.call("INCR", KEYS[1])
if current > tonumber(ARGV[1]) then
return 0
end
if current == 1 then
redis.call("EXPIRE", KEYS[1], ARGV[2])
end
return 1
`, []string{key}, r.limit, int(r.window.Seconds())).Result()
return err == nil && result == int64(1)
}
4. 中间件实现
HTTP 请求速率限制
func RateLimitMiddleware(limiter *RateLimiter) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if!limiter.Allow() {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
}
速率限制策略比较
策略 |
优点 |
缺点 |
使用场景 |
固定窗口 |
实现简单 |
在边界时间段可能导致突发流量 |
简单的 API 保护 |
滑动窗口 |
更精确 |
计算开销较高 |
精确的速率控制 |
令牌桶 |
处理突发流量 |
实现复杂 |
网络流量管理 |
最佳实践
graph TD
A[速率限制最佳实践] --> B[清晰的错误处理]
A --> C[可配置的限制]
A --> D[日志记录和监控]
A --> E[优雅降级]
性能考虑因素
- 使用原子操作
- 最小化锁争用
- 实现高效的数据结构
- 考虑缓存机制
错误处理与弹性
实现健壮的错误处理
func (rl *RateLimiter) ExecuteWithRateLimit(fn func() error) error {
if!rl.Allow() {
return errors.New("rate limit exceeded")
}
return fn()
}
在 LabEx,我们强调根据特定系统要求定制灵活高效的速率限制策略的重要性。