去如何基于IP限制HTTP访问频率

  介绍

小编给大家分享一下走如何基于IP限制HTTP访问频率,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

创建一个简单的中间件实现基于IP限制HTTP访问频率。

<强>简单的HTTP服务

让我们从创建一个简单的HTTP服务开始,它有非常简单的终端。但是,因为它的访问频率可能非常高,因此我们要为它添加频率限制。

package 主要      import  (   ,“log"   ,“;net/http"   )      func  main (), {   ,mux :=, http.NewServeMux ()   ,mux.HandleFunc (“/?, okHandler)      ,if  err :=, http.ListenAndServe (“: 8888,,, mux);, err  !=, nil  {   log.Fatalf才能(“unable 用start 服务器:,% s",, err.Error ())   ,}   }      func  okHandler (w  http.ResponseWriter, r  * http.Request), {   ,//某些消耗很高的数据库请求   ,w.Write([]字节(“alles  gut"))   }

通过主。去我们启动服务,监听:8888端口,这样我们就有了一个简单的终端/?/p>

<强烈>golang.org/x/time/rate

我们将使用名为x/时间/速度的包,它提供了一个令牌桶速率限制器算法.rate #限幅器控制允许事件发生的频率。它实现了一个大小为b的“令牌桶”,最初是满的,并以每秒r的速度重新填充令牌。通俗地讲,就是在任何足够大的时间间隔内,限制器将速率限制为每秒r个令牌,最大突发大小为b个事件。

由于我们希望实现每个IP地址的速率限制器,我们还需要维护一个限制器映射。

package 主要      import  (   ,“sync"      ,“;golang.org/x/time/rate"   )//IPRateLimiter 。   type  IPRateLimiter  struct  {   ,ips  map [string] * rate.Limiter   mu  * sync.RWMutex   r  rate.Limit   b  int   }//NewIPRateLimiter 。   func  NewIPRateLimiter (r  rate.Limit, b  int), * IPRateLimiter  {   ,小姐::=,,IPRateLimiter {   ips才能:使(map [string] * rate.Limiter),   μ才能:,,sync.RWMutex {},   接待员:,r,才能   b, b:大敌;   ,}      return 我   }//,AddIP 创建了一个新的速率限制器,并将其添加到,ips 映射中,//,使用,IP地址作为密钥   func (小姐:* IPRateLimiter), AddIP (ip 字符串),* rate.Limiter  {   ,i.mu.Lock ()   ,defer  i.mu.Unlock ()      ,limiter :=, rate.NewLimiter(天然橡胶,i.b)      ,i.ips (ip),=,限幅器      return 限制器   }//,GetLimiter 返回所提供的IP地址的速率限制器(如果存在的话)。//,否则调用,AddIP 将,IP 地址添加到映射中   func (小姐:* IPRateLimiter), GetLimiter (ip 字符串),* rate.Limiter  {   ,i.mu.Lock ()   ,限幅器,exists :=, i.ips (ip)      ,if  ! exists , {   i.mu.Unlock才能()   return 才能i.AddIP (ip)   ,}      ,i.mu.Unlock ()      return 限制器   }

NewIPRateLimiter创建一个IP限制器实例,HTTP服务器必须调用这个实例的GetLimiter来获得指定IP的限制器(从映射或生成一个新的)。

<强>中间件

让我们升级的HTTP服务并将中间件添加到所有端点,如果IP达到限制,它将响应429年太多的请求,否则,它将继续该请求。

每一个经过中间件的请求,我们都会调用limitMiddleware函数中的全局方法允许()。如果存储桶中没有令牌了,该方法会返回假,该请求会收429到太多的请求的响应。否则允许()方法将消耗一个令牌,并将请求传递给下一个程序。

package 主要      import  (   ,“log"   ,“;net/http"   )      var  limiter =, NewIPRateLimiter (1, 5)      func  main (), {   ,mux :=, http.NewServeMux ()   ,mux.HandleFunc (“/?, okHandler)      ,if  err :=, http.ListenAndServe (“: 8888,,, limitMiddleware (mux);, err  !=, nil  {   log.Fatalf才能(“unable 用start 服务器:,% s",, err.Error ())   ,}   }      func  limitMiddleware (next  http.Handler), http.Handler  {   ,return  http.HandlerFunc (func (w  http.ResponseWriter, r  * http.Request), {   limiter 才能;:=,limiter.GetLimiter (r.RemoteAddr)   if 才能;! limiter.Allow (), {   ,,http.Error (w, http.StatusText (http.StatusTooManyRequests), http.StatusTooManyRequests)   ,才能回来   ,,}      next.ServeHTTP才能(w, r)   ,})   }      func  okHandler (w  http.ResponseWriter, r  * http.Request), {   ,//非常重要的数据请求(译者注:这句话没理解到位)   ,w.Write([]字节(“alles  gut"))   }

去如何基于IP限制HTTP访问频率