golang配额管理与速率限制工具插件库equalizer的使用
Golang配额管理与速率限制工具插件库equalizer的使用
equalizer
是一个Go语言实现的简单易用的速率限制器集合,可以用于限制对数据库、API或文件等任何资源的请求速率。
Equalizer
Equalizer
是一个根据先前请求结果调整请求速率的限流器。如果之前的尝试失败,Equalizer会降低请求速率以避免系统过载;如果之前的尝试成功,Equalizer会提高请求速率以充分利用可用容量。
使用示例
// 创建一个随机偏移管理器
offset := equalizer.NewRandomOffset(96)
// 创建一个Equalizer,位图大小为96,16个保留正数位,使用随机偏移管理器
eq := equalizer.NewEqualizer(96, 16, offset)
// 非阻塞式配额请求
haveQuota := eq.TryAcquire()
// 请求成功后更新状态
eq.Success(1)
性能基准
BenchmarkEqualizer_ShortTryAcquireStep-16 31538967 38.33 ns/op 0 B/op 0 allocs/op
BenchmarkEqualizer_ShortTryAcquireRandom-16 37563639 31.66 ns/op 0 B/op 0 allocs/op
BenchmarkEqualizer_ShortNotify-16 29519719 40.43 ns/op 0 B/op 0 allocs/op
BenchmarkEqualizer_LongTryAcquireStep-16 32084402 38.36 ns/op 0 B/op 0 allocs/op
BenchmarkEqualizer_LongTryAcquireRandom-16 39996501 30.37 ns/op 0 B/op 0 allocs/op
BenchmarkEqualizer_LongNotify-16 29648655 40.46 ns/op 0 B/op 0 allocs/op
Slider
Slider
跟踪最近时间窗口内已处理的请求数量。如果请求数超过限制,速率限制器将阻止新请求,直到窗口向前移动。实现了equalizer.Limiter
接口。
使用示例
// 创建一个Slider,窗口大小为1秒,滑动间隔100毫秒,容量32
slider := equalizer.NewSlider(time.Second, 100*time.Millisecond, 32)
// 非阻塞式配额请求
haveQuota := slider.TryAcquire()
// 阻塞式调用
slider.Acquire(context.Background())
性能基准
BenchmarkSlider_TryAcquire-16 293645348 4.033 ns/op 0 B/op 0 allocs/op
BenchmarkRateLimiter_Allow-16 9362382 127.4 ns/op 0 B/op 0 allocs/op
Token Bucket
TokenBucket
维护固定数量的令牌。每个令牌代表一个可以处理的请求。当发出请求时,速率限制器检查是否有可用令牌。如果有,则处理请求并移除一个令牌;如果没有,则阻塞请求直到有令牌可用。实现了equalizer.Limiter
接口。
使用示例
// 创建一个TokenBucket,容量32,补充间隔100毫秒
tokenBucket := equalizer.NewTokenBucket(32, 100*time.Millisecond)
// 非阻塞式配额请求
haveQuota := tokenBucket.TryAcquire()
// 阻塞式调用
tokenBucket.Acquire(context.Background())
性能基准
BenchmarkTokenBucket_TryAcquire-16 304653043 3.909 ns/op 0 B/op 0 allocs/op
BenchmarkRateLimiter_Allow-16 9362382 127.4 ns/op 0 B/op 0 allocs/op
完整示例Demo
package main
import (
"context"
"fmt"
"time"
"github.com/reugn/equalizer"
)
func main() {
// Equalizer示例
offset := equalizer.NewRandomOffset(96)
eq := equalizer.NewEqualizer(96, 16, offset)
if eq.TryAcquire() {
fmt.Println("Equalizer: 获取配额成功")
eq.Success(1)
}
// Slider示例
slider := equalizer.NewSlider(time.Second, 100*time.Millisecond, 32)
if slider.TryAcquire() {
fmt.Println("Slider: 获取配额成功")
}
// 带超时的阻塞调用
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := slider.Acquire(ctx); err == nil {
fmt.Println("Slider: 阻塞获取配额成功")
}
// TokenBucket示例
tokenBucket := equalizer.NewTokenBucket(32, 100*time.Millisecond)
if tokenBucket.TryAcquire() {
fmt.Println("TokenBucket: 获取配额成功")
}
// 阻塞调用
if err := tokenBucket.Acquire(context.Background()); err == nil {
fmt.Println("TokenBucket: 阻塞获取配额成功")
}
}
许可证
使用MIT许可证授权。
更多关于golang配额管理与速率限制工具插件库equalizer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复