我已经为1天的api登录创建了限制50 req的函数
无限制= 50
package middleware
import (
"log"
"net"
"net/http"
"sync"
"time"
"golang.org/x/time/rate"
)
// Create a custom request struct which holds the rate limiter for each
// visitor and the last time that the request was seen.
type request struct {
limiter *rate.Limiter
lastSeen time.Time
}
// Change the the map to hold values of the type request.
// defaultTime using 3 minutes
var requests = make(map[string]*request)
var mu sync.Mutex
func getRequest(ip string, limit int) *rate.Limiter {
mu.Lock()
defer mu.Unlock()
v, exists := requests[ip]
if !exists {
limiter := rate.NewLimiter(1, limit)
requests[ip] = &request{limiter, time.Now()}
return limiter
}
// Update the last seen time for the visitor.
v.lastSeen = time.Now()
return v.limiter
}
func throttle(next http.Handler, limit int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
log.Println(err.Error())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
limiter := getRequest(ip, limit)
fmt.Println(limiter.Allow())
if limiter.Allow() == false {
http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
其正确吗?
因为我尝试仍然通过,功能限制不起作用
我怀疑是否有NewLimiter()
limiter := rate.NewLimiter(1, limit)
这意味着1个用户只能请求登录50 req /天? (我已经读过文档,但我听不懂)
NewLimited(1, 50)
表示1 req / sec,最多突发50个请求。这是一个令牌桶,这意味着有50个令牌,每个接受的API调用都用完一个令牌,然后以给定的速率(最高burst
)重新生成令牌。您的代码正在为每个IP地址创建一个限制器,所以这是每个IP地址的限制(我想您大概是一个用户的IP地址)。
[如果您在单个持久性服务器上运行,并且服务器和代码从不重启,那么通过指定50 / (3600*24)
的速率和50的突发次数,每位用户每天可以获得50要求/类似的值。(注意:3600*24
是一天中的秒数)。但是,您使用的速率限制程序包并非设计用于这种粗略的速率限制(按每天的请求数量)-旨在防止短期内在繁忙流量下服务器过载(按每秒的请求数量) )。
您可能想要一个与数据库或类似数据库一起工作的速率限制器(也许使用令牌桶方案,因为可以高效地实现)。可能在某个地方有一个包装,但是我不知道我的头顶上有一个。
func NewLimiter(r Limit, b int) *Limiter
NewLimiter返回一个新的限制器,该限制器允许事件达到r和最多允许突发b个令牌。
因此第一个参数是速率限制,而不是第二个。突发次数是您希望允许的请求数,比速率限制更快]-通常使用1
的值来禁止爆发,任何更高的值都会让此请求数早于常规速率-极限开始。反正...
要创建您需要的rate.Limit
,可以使用助手功能rate.Every()
:
rt := rate.Every(24*time.Hour / 50)
limiter := rate.NewLimiter(rt, 1)