簡介
常用的限流算法有兩種:漏桶算法和令牌桶算法。
漏桶算法
漏桶算法思路很簡單,水(請求)先進入到漏桶裏,漏桶以一定的速度出水,當水流入速度過大會直接溢出,可以看出漏桶算法能強行限制數據的傳輸速率。
令牌桶算法
對於很多應用場景來說,除了要求能夠限制數據的平均傳輸速率外,還要求允許某種程度的突發傳輸。這時候漏桶算法可能就不合適了,令牌桶算法更爲適合。如下圖所示,令牌桶算法的原理是系統會以一個恆定的速度往桶裏放入令牌,而如果請求需要被處理,則需要先從桶裏獲取一個令牌,當桶裏沒有令牌可取時,則拒絕服務。
以上內容來自網絡,指望我寫簡介,※=○☆(__*)Zzz
go自帶令牌桶rate
標準包如下,自行科學上網獲取,或者去國內代理下載
"golang.org/x/time/rate"
創建實例
//參數Limit,生成令牌速率,每秒多少個,參數b:桶最大容量
limiter := rate.NewLimiter(1,5)
使用方法
三個方法中,推薦使用wait方法
//WaitN 函數,等待獲取令牌,這裏設置最大等待時長2s
//如果在最大等待時長內無法獲取,則直接跳出,不會進行等待
//Wait函數等價於WaitN(ctx,1)
ctx,_:= context.WithTimeout(context.Background(),time.Second*2)
err := limiter.WaitN(ctx,2)
//AllowN 當沒有可用或足夠的事件時,返回false
//Allow函數等同於AllowN(time.Now(),1)
limiter.AllowN(time.Now(),2)
//ReserveN 返回對象Reservation ,標識調用者需要等多久才能等到n個事件發生(意思就是等多久令牌池中至少含有n個令牌)。
//Reserve函數等價於ReserveN(time.Now(),1)
limiter.ReserveN(time.Now(),2)
實戰使用
這裏結合gin框架使用,將限流服務當做gin的一箇中間件
至於如何將gin和go-kit搭配使用,以後會出文章詳解
var limiter * rate.Limiter
func init(){
limiter = rate.NewLimiter(100,1024)
}
func RateLimiter(c *gin.Context){
ctx,_:=context.WithTimeout(context.Background(),time.Second*10)
if err := limiter.Wait(ctx);err==nil{
c.Next()
}else {
c.String(503 ,"系統繁忙,請稍後重試:"+err.Error())
c.Abort()
}
}
將這個中間件註冊到gin服務服務中,此時,基於令牌桶的限流功能就做好了。
g.Use(middle.RateLimiter)