大猩猩mux限速器



我正在尝试实现http请求限制器,允许每个用户通过其用户名每秒10个请求。最多可以向服务器发送10个请求,包括正在处理的请求。以下是我参考速率限制所实现的。

func init() {
go cleanupVisitors()
}
func getVisitor(username string) *rate.Limiter {
mu.Lock()
defer mu.Unlock()
v, exists := visitors[username]
if !exists {
limiter := rate.NewLimiter(10, 3)
visitors[username] = &visitor{limiter, time.Now()}
return limiter
}
v.lastSeen = time.Now()
return v.limiter
}
func cleanupVisitors() {
for {
time.Sleep(time.Minute)
mu.Lock()
for username, v := range visitors {
if time.Since(v.lastSeen) > 1*time.Minute {
delete(visitors, username)
}
}
mu.Unlock()
}
}
func limit(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mappedArray := hotelapi.SearchResponse{}
mappedArray.StartTime = time.Now().Format("2006-02-01 15:04:05.000000")
mappedArray.EndTime = time.Now().Format("2006-02-01 15:04:05.000000")
userName := r.FormValue("username")
limiter := getVisitor(userName)
if !limiter.Allow() {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusTooManyRequests)
mappedArray.MessageInfo = http.StatusText(http.StatusTooManyRequests)
mappedArray.ErrorCode = strconv.Itoa(http.StatusTooManyRequests)
json.NewEncoder(w).Encode(mappedArray)
return
}
next.ServeHTTP(w, r)
})
}
func route() {
r := mux.NewRouter()
r.PathPrefix("/hello").HandlerFunc(api.ProcessHello).Methods("GET")
ws := r.PathPrefix("/index.php").HandlerFunc(api.ProcessWs).Methods("GET", "POST").Subrouter()
r.Use(panicRecovery)
ws.Use(limit)
http.HandleFunc("/favicon.ico", faviconHandler)
if config.HTTPSEnabled {
err := http.ListenAndServeTLS(":"+config.Port, config.HTTPSCertificateFilePath, config.HTTPSKeyFilePath, handlers.CompressHandlerLevel(r, gzip.BestSpeed))
if err != nil {
fmt.Println(err)
log.Println(err)
}
} else {
err := http.ListenAndServe(":"+config.Port, handlers.CompressHandler(r))
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
}

我有几个问题。

我只想限制/index.php,而不是/hello。我用subroute实现了。是正确的方式吗?

限制中间件并不像我假设的那样是限制的。它允许一个成功的请求,所有其他请求返回,请求过多错误。

我在这里错过了什么?

?

子模式是大猩猩提出的解决方案,尽管组织建议很小:

r := mux.NewRouter()
r.HandlerFunc("/hello", api.ProcessHello).Methods("GET")
r.HandleFunc("/favicon.ico", faviconHandler)
r.Use(panicRecovery)
ws := r.PathPrefix("/index.php").Subrouter()
ws.Use(limit)
ws.HandlerFunc(api.ProcessWs).Methods("GET", "POST")

你似乎是调用你的中间件不仅通过Use()方法,但也调用它的处理程序上的ListenAndServe,我也看到从大猩猩相同的例子,一个更清晰的方式来接近这是:

server := &http.Server{
Addr:         "0.0.0.0:8080",
// Good practice to set timeouts to avoid Slowloris attacks.
WriteTimeout: time.Second * 15,
ReadTimeout:  time.Second * 15,
IdleTimeout:  time.Second * 60,
Handler: router, // Pass our instance of gorilla/mux in.
}
fmt.Println("starting server")
if err := server.ListenAndServe(); err != nil {
fmt.Println(err)
}

同样,从你的来源来看,你正在实现的速率限制模式是每个用户的速率限制,但是你使用用户名而不是他们的ip来限制他们的请求,你的问题开始时没有澄清你是希望每个用户的速率限制还是速率限制可以向端点完成的请求数量-所以也许你也可能因此而得到意想不到的行为。

相关内容

  • 没有找到相关文章

最新更新