golang.org/x/time/rate api请求的速率限制

问题描述 投票:0回答:2

我已经为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 /天? (我已经读过文档,但我听不懂)

go limit rate
2个回答
0
投票

NewLimited(1, 50)表示1 req / sec,最多突发50个请求。这是一个令牌桶,这意味着有50个令牌,每个接受的API调用都用完一个令牌,然后以给定的速率(最高burst)重新生成令牌。您的代码正在为每个IP地址创建一个限制器,所以这是每个IP地址的限制(我想您大概是一个用户的IP地址)。

[如果您在单个持久性服务器上运行,并且服务器和代码从不重启,那么通过指定50 / (3600*24)的速率和50的突发次数,每位用户每天可以获得50要求/类似的值。(注意:3600*24是一天中的秒数)。但是,您使用的速率限制程序包并非设计用于这种粗略的速率限制(按每天的请求数量)-旨在防止短期内在繁忙流量下服务器过载(按每秒的请求数量) )。

您可能想要一个与数据库或类似数据库一起工作的速率限制器(也许使用令牌桶方案,因为可以高效地实现)。可能在某个地方有一个包装,但是我不知道我的头顶上有一个。


0
投票

rate docs

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)
© www.soinside.com 2019 - 2024. All rights reserved.