英文:
golang rate limit per minute
问题
如何实现每分钟限制20个请求?
import "golang.org/x/time/rate"
limiter := rate.NewLimiter(rate.Every(1*time.Minute), 20)
for {
limiter.Wait()
//更多代码
}
这段代码并不能实现预期的效果。它只允许在第一分钟内发送20个请求,然后每分钟只允许发送1个请求。预期的效果是在第一分钟内发送20个请求(不需要均匀分布,比如每3秒1个请求),然后在第二分钟再发送20个请求。在任何1分钟的时间间隔内,不能发送超过20个请求。
你可以参考我的解决方案:https://stackoverflow.com/a/72452542
英文:
How to rate limit 20 requests per minute?
import "golang.org/x/time/rate"
limiter := rate.NewLimiter(rate.Every(1*time.Minute), 20)
for {
limiter.Wait()
//more code
}
This does not work. What that does is, it allows first 20 requests, then only allows 1 request per minute. What is expected is 20 requests on the first minute(Need not be evenly spread like 1 per 3 seconds) and then 20 more requests on the second minute. At any 1 minute interval, there cannot be more than 20 requests sent.
My solution: https://stackoverflow.com/a/72452542
答案1
得分: 5
设置您期望的速率:
limiter := rate.NewLimiter(rate.Every(1*time.Minute/20), 20)
for {
limiter.Wait()
//更多代码
}
playground链接:https://go.dev/play/p/ZpxpHj0vK7P
您似乎正在寻找一种允许“每分钟最多20个突发,每分钟重置一次”的方法。以下是一个示例:
type Limiter struct {
maxCount int
count int
ticker *time.Ticker
ch chan struct{}
}
func (l *Limiter) run() {
for {
// 如果计数器达到0:阻塞直到下一个tick
if l.count <= 0 {
<-l.ticker.C
l.count = l.maxCount
}
// 否则:
// 每次在通道上发送一条消息时,将“count”减少一次,
// 当ticker发出信号时,将“count”重置为“maxCount”
select {
case l.ch <- struct{}{}:
l.count--
case <-l.ticker.C:
l.count = l.maxCount
}
}
}
func (l *Limiter) Wait() {
<-l.ch
}
func NewLimiter(d time.Duration, count int) *Limiter {
l := &Limiter{
maxCount: count,
count: count,
ticker: time.NewTicker(d),
ch: make(chan struct{}),
}
go l.run()
return l
}
链接:https://go.dev/play/p/5WiOJL5nqCy
英文:
Set the rate you expect :
limiter := rate.NewLimiter(rate.Every(1*time.Minute/20), 20)
for {
limiter.Wait()
//more code
}
playground: https://go.dev/play/p/ZpxpHj0vK7P
You seem to look for something that allows "bursts of up to 20, reset every minute". Here is a go at it :
type Limiter struct {
maxCount int
count int
ticker *time.Ticker
ch chan struct{}
}
func (l *Limiter) run() {
for {
// if counter has reached 0: block until next tick
if l.count <= 0 {
<-l.ticker.C
l.count = l.maxCount
}
// otherwise:
// decrement 'count' each time a message is sent on channel,
// reset 'count' to 'maxCount' when ticker says so
select {
case l.ch <- struct{}{}:
l.count--
case <-l.ticker.C:
l.count = l.maxCount
}
}
}
func (l *Limiter) Wait() {
<-l.ch
}
func NewLimiter(d time.Duration, count int) *Limiter {
l := &Limiter{
maxCount: count,
count: count,
ticker: time.NewTicker(d),
ch: make(chan struct{}),
}
go l.run()
return l
}
答案2
得分: 1
你可以像这样使用time.Tick
和for-select
:
package main
import (
"fmt"
"time"
)
func main() {
max := 20
limiter := time.Tick(1 * time.Minute)
exit := make(chan struct{})
go func() {
count := 0
exit2 := 0
defer func() {
exit <- struct{}{}
}()
for {
select {
case <-limiter:
count = 0
fmt.Println("exit2: ", exit2)
if exit2 == 3 {
return
}
exit2++
default:
if count == max {
continue
}
fmt.Println("accepting request", count)
count++
}
}
}()
<-exit
}
英文:
you can use time.Tick
and for-select
like this:
package main
import (
"fmt"
"time"
)
func main() {
max := 20
limiter := time.Tick(1 * time.Minute)
exit := make(chan struct{})
go func() {
count := 0
exit2 := 0
defer func() {
exit <- struct{}{}
}()
for {
select {
case <-limiter:
count = 0
fmt.Println("exit2: ", exit2)
if exit2 == 3 {
return
}
exit2++
default:
if count == max {
continue
}
fmt.Println("accepting request", count)
count++
}
}
}()
<-exit
}
答案3
得分: 0
请尝试以下代码:
import (
"fmt"
"time"
)
func main() {
limiter := time.Tick(3 * time.Minute) // 从20改为3,因为我意识到你想要每分钟20个请求,而不是每20分钟1个请求
for true {
<-limiter
fmt.Println(time.Now())
}
}
我实际上没有尝试过20 * time.Minute
作为值,但我尝试了200 * time.Millisecond
,它可以正常工作。这是我的响应:
2022-05-31 00:06:13.447108 -0600 MDT m=+0.200889915
2022-05-31 00:06:13.651373 -0600 MDT m=+0.405148283
2022-05-31 00:06:13.851522 -0600 MDT m=+0.605291066
2022-05-31 00:06:14.051481 -0600 MDT m=+0.805244205
2022-05-31 00:06:14.250144 -0600 MDT m=+1.003900790
2022-05-31 00:06:14.450952 -0600 MDT m=+1.204703429
2022-05-31 00:06:14.648365 -0600 MDT m=+1.402110595
2022-05-31 00:06:14.848223 -0600 MDT m=+1.601961982
2022-05-31 00:06:15.04909 -0600 MDT m=+1.802823232
2022-05-31 00:06:15.250164 -0600 MDT m=+2.003891217
英文:
try this
import (
"fmt"
"time"
)
func main() {
limiter := time.Tick(3 * time.Minute) //changed from 20 to 3 because i realized you wanted 20 requests per minute, not 1 request per 20 minutes
for true {
<-limiter
fmt.Println(time.Now())
}
}
I haven't actually tried with 20 * time.Minute
as the value, but I tried 200 * time.Milisecond
and it worked. Here was my response
2022-05-31 00:06:13.447108 -0600 MDT m=+0.200889915
2022-05-31 00:06:13.651373 -0600 MDT m=+0.405148283
2022-05-31 00:06:13.851522 -0600 MDT m=+0.605291066
2022-05-31 00:06:14.051481 -0600 MDT m=+0.805244205
2022-05-31 00:06:14.250144 -0600 MDT m=+1.003900790
2022-05-31 00:06:14.450952 -0600 MDT m=+1.204703429
2022-05-31 00:06:14.648365 -0600 MDT m=+1.402110595
2022-05-31 00:06:14.848223 -0600 MDT m=+1.601961982
2022-05-31 00:06:15.04909 -0600 MDT m=+1.802823232
2022-05-31 00:06:15.250164 -0600 MDT m=+2.003891217
答案4
得分: 0
我的翻译如下:
我的解决方案
import (
"sync"
"time"
)
type Limiter interface {
Wait()
}
type limiter struct {
tick time.Duration
count uint
entries []time.Time
index uint
mutex sync.Mutex
}
func NewLimiter(tick time.Duration, count uint) Limiter {
l := limiter{
tick: tick,
count: count,
index: 0,
}
l.entries = make([]time.Time, count)
before := time.Now().Add(-2 * tick)
for i, _ := range l.entries {
l.entries[i] = before
}
return &l
}
func (l *limiter) Wait() {
l.mutex.Lock()
defer l.mutex.Unlock()
last := &l.entries[l.index]
next := last.Add(l.tick)
now := time.Now()
if now.Before(next) {
time.Sleep(next.Sub(now))
}
*last = time.Now()
l.index = l.index + 1
if l.index == l.count {
l.index = 0
}
}
希望对你有帮助!
英文:
My solution
import (
"sync"
"time"
)
type Limiter interface {
Wait()
}
type limiter struct {
tick time.Duration
count uint
entries []time.Time
index uint
mutex sync.Mutex
}
func NewLimiter(tick time.Duration, count uint) Limiter {
l := limiter{
tick: tick,
count: count,
index: 0,
}
l.entries = make([]time.Time, count)
before := time.Now().Add(-2 * tick)
for i, _ := range l.entries {
l.entries[i] = before
}
return &l
}
func (l *limiter) Wait() {
l.mutex.Lock()
defer l.mutex.Unlock()
last := &l.entries[l.index]
next := last.Add(l.tick)
now := time.Now()
if now.Before(next) {
time.Sleep(next.Sub(now))
}
*last = time.Now()
l.index = l.index + 1
if l.index == l.count {
l.index = 0
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论