Ограничение скорости с golang .org / x / time / rate api request - PullRequest
0 голосов
/ 23 марта 2020

я уже создал функцию для лимита 50 req для входа в API через 1 день

var limit = 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)
    })
}

это правильно?

, потому что я пробую его до сих пор pass, функция limit не работает

я сомневаюсь с NewLimiter ()

 limiter := rate.NewLimiter(1, limit)

это означает, что 1 пользователь может только запросить логин 50 req / days? (я уже читал c, но я не понимаю)

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

Из документов rate :

func NewLimiter(r Limit, b int) *Limiter

NewLimiter возвращает новый лимитер, который разрешает событиям до скорости r и разрешает выбросы максимум для b токенов.


Таким образом, первый параметр - это ограничение скорости, а не второй. Burst - это количество запросов, которые вы хотите разрешить, которые происходят быстрее , чем ограничение скорости - обычно один использует значение 1, чтобы запретить пакетную передачу, все, что выше, пропустит это количество запросов раньше обычного начинает действовать ограничение скорости. В любом случае ...

Чтобы создать rate.Limit для своих нужд, вы можете использовать вспомогательную функцию rate.Every():

rt := rate.Every(24*time.Hour / 50)

limiter := rate.NewLimiter(rt, 1)
0 голосов
/ 23 марта 2020

NewLimited(1, 50) означает 1 запрос / сек c с пакетом до 50 запросов. Это набор токенов, что означает, что имеется 50 токенов, каждый принятый вызов API использует один токен, и токены восстанавливаются с заданной скоростью, вплоть до burst. Ваш код создает ограничение для каждого IP-адреса, поэтому это ограничение для каждого IP-адреса (которое, по-моему, приблизительно соответствует одному IP-адресу одного пользователя).

Если вы работаете на одном постоянном сервере, и сервер и код никогда не перезапускаются, тогда вы можете получить что-то вроде 50req / day на пользователя, указав скорость 50 / (3600*24) и пакетную передачу 50. (Примечание: 3600*24 - это количество секунд в дне ). Но используемый вами пакет ограничения скорости не предназначен для такого грубого ограничения скорости (порядка запросов в день) - он предназначен для предотвращения перегрузки сервера в условиях интенсивного трафика c в краткосрочной перспективе (порядка запросов в секунду).

Возможно, вам нужен ограничитель скорости, который работает с базой данных или аналогичным образом (возможно, с использованием схемы маркеров, так как это может быть эффективно реализовано). Возможно, где-то есть посылка для этого, но я не знаю ни одной из моих голов.

...