介绍
小编给大家分享一下走如何基于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访问频率