golang实现高效定时速率限制功能插件库go-rate的使用
go-rate - Golang高效定时速率限制功能插件库
go-rate是一个专为多种使用场景设计的速率限制器,包括服务器端垃圾信息防护和防止API调用过载等。
使用说明
导入github.com/beefsack/go-rate
并使用rate.New(limit int, interval time.Duration)
函数创建一个新的速率限制器。
速率限制器提供Wait()
和Try() (bool, time.Duration)
方法,分别用于阻塞和非阻塞功能。
示例代码
阻塞式速率限制
这个示例演示如何将输出速率限制为每秒3次。
package main
import (
"fmt"
"time"
"github.com/beefsack/go-rate"
)
func main() {
rl := rate.New(3, time.Second) // 3 times per second
begin := time.Now()
for i := 1; i <= 10; i++ {
rl.Wait()
fmt.Printf("%d started at %s\n", i, time.Now().Sub(begin))
}
// Output:
// 1 started at 12.584us
// 2 started at 40.13us
// 3 started at 44.92us
// 4 started at 1.000125362s
// 5 started at 1.000143066s
// 6 started at 1.000144707s
// 7 started at 2.000224641s
// 8 started at 2.000240751s
// 9 started at 2.00024244s
// 10 started at 3.000314332s
}
多限制器组合的阻塞式速率限制
这个示例演示如何组合两个速率限制器,一个限制每秒1次,另一个限制每3秒2次。
package main
import (
"fmt"
"time"
"github.com/beefsack/go-rate"
)
func main() {
begin := time.Now()
rl1 := rate.New(1, time.Second) // Once per second
rl2 := rate.New(2, time.Second*3) // 2 times per 3 seconds
for i := 1; i <= 10; i++ {
rl1.Wait()
rl2.Wait()
fmt.Printf("%d started at %s\n", i, time.Now().Sub(begin))
}
// Output:
// 1 started at 11.197us
// 2 started at 1.00011941s
// 3 started at 3.000105858s
// 4 started at 4.000210639s
// 5 started at 6.000189578s
// 6 started at 7.000289992s
// 7 started at 9.000289942s
// 8 started at 10.00038286s
// 9 started at 12.000386821s
// 10 started at 13.000465465s
}
非阻塞式速率限制
这个示例演示非阻塞速率限制,例如可用于限制聊天客户端中的垃圾信息。
package main
import (
"fmt"
"time"
"github.com/beefsack/go-rate"
)
var rl = rate.New(3, time.Second) // 3 times per second
func say(message string) {
if ok, remaining := rl.Try(); ok {
fmt.Printf("You said: %s\n", message)
} else {
fmt.Printf("Spam filter triggered, please wait %s\n", remaining)
}
}
func main() {
for i := 1; i <= 5; i++ {
say(fmt.Sprintf("Message %d", i))
}
time.Sleep(time.Second / 2)
say("I waited half a second, is that enough?")
time.Sleep(time.Second / 2)
say("Okay, I waited a second.")
// Output:
// You said: Message 1
// You said: Message 2
// You said: Message 3
// Spam filter triggered, please wait 999.980816ms
// Spam filter triggered, please wait 999.976704ms
// Spam filter triggered, please wait 499.844795ms
// You said: Okay, I waited a second.
}
作者
- Michael Alexander
- Geert-Johan Riemer
- Matt T. Proud
更多关于golang实现高效定时速率限制功能插件库go-rate的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现高效定时速率限制功能插件库go-rate的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang高效定时速率限制库go-rate使用指南
go-rate是一个高效的Golang速率限制库,它提供了灵活的速率限制功能,可以帮助开发者控制API调用、数据库访问等操作的频率。
安装
go get github.com/beefsack/go-rate
基本使用
1. 简单的速率限制
package main
import (
"fmt"
"time"
"github.com/beefsack/go-rate"
)
func main() {
// 创建一个限制器:每秒最多5次操作
rl := rate.New(5, time.Second)
for i := 0; i < 10; i++ {
// Try()尝试获取令牌,返回是否成功和需要等待的时间
ok, remaining := rl.Try()
if !ok {
fmt.Printf("请求 %d 被限流,需要等待 %v\n", i, remaining)
time.Sleep(remaining)
continue
}
fmt.Printf("请求 %d 通过\n", i)
}
}
2. 使用Wait()方法
func main() {
rl := rate.New(2, time.Second) // 每秒2次
for i := 0; i < 5; i++ {
// Wait()会阻塞直到可以执行
rl.Wait()
fmt.Printf("执行操作 %d 在 %v\n", i, time.Now().Format("15:04:05.000"))
}
}
高级功能
1. 突发限制
func main() {
// 允许突发3个请求,然后限制为每秒1个
rl := rate.New(1, time.Second)
rl.SetBurst(3)
for i := 0; i < 5; i++ {
ok, _ := rl.Try()
if ok {
fmt.Printf("请求 %d 通过\n", i)
} else {
fmt.Printf("请求 %d 被限流\n", i)
time.Sleep(time.Second)
}
}
}
2. 动态调整速率
func main() {
rl := rate.New(10, time.Minute) // 每分钟10次
// 动态调整速率
rl.SetRate(20, time.Minute) // 调整为每分钟20次
// 检查当前速率
rate, interval := rl.Rate()
fmt.Printf("当前速率: %d 次每 %v\n", rate, interval)
}
实际应用示例
API调用限流
package main
import (
"fmt"
"net/http"
"time"
"github.com/beefsack/go-rate"
)
var apiRateLimiter = rate.New(100, time.Minute) // 每分钟100次API调用
func makeAPICall(url string) (*http.Response, error) {
// 等待直到可以执行
apiRateLimiter.Wait()
resp, err := http.Get(url)
if err != nil {
return nil, err
}
return resp, nil
}
func main() {
urls := []string{
"https://api.example.com/endpoint1",
"https://api.example.com/endpoint2",
// 更多URL...
}
for _, url := range urls {
resp, err := makeAPICall(url)
if err != nil {
fmt.Printf("调用 %s 失败: %v\n", url, err)
continue
}
fmt.Printf("调用 %s 成功,状态码: %d\n", url, resp.StatusCode)
resp.Body.Close()
}
}
数据库操作限流
package main
import (
"database/sql"
"fmt"
"time"
_ "github.com/lib/pq"
"github.com/beefsack/go-rate"
)
var dbRateLimiter = rate.New(50, time.Second) // 每秒最多50次数据库操作
func queryDB(db *sql.DB, query string) (*sql.Rows, error) {
dbRateLimiter.Wait()
return db.Query(query)
}
func main() {
db, err := sql.Open("postgres", "user=postgres dbname=test sslmode=disable")
if err != nil {
panic(err)
}
defer db.Close()
queries := []string{
"SELECT * FROM users",
"SELECT * FROM orders",
// 更多查询...
}
for _, q := range queries {
rows, err := queryDB(db, q)
if err != nil {
fmt.Printf("查询失败: %v\n", err)
continue
}
defer rows.Close()
fmt.Printf("查询成功: %s\n", q)
}
}
性能考虑
go-rate在设计上考虑了高性能:
- 使用原子操作而非锁,减少竞争
- 内存占用小
- 无外部依赖
对于大多数应用场景,go-rate的性能开销可以忽略不计。
与其他库的比较
- go-rate API更简单
- 提供了Try()方法可以立即知道是否被限流
- 支持动态调整速率
相比uber-go/ratelimit:
- go-rate支持更灵活的速率设置
- 提供了突发限制功能
go-rate是一个轻量级但功能完整的速率限制库,适合大多数Golang应用的限流需求。