golang 限流控制

2021-10-14 17:15:12 字數 2566 閱讀 1592

限流

日常開發中,一般會遇到幾種場景需要限流,比如有個api-server, 需要限制單個使用者的呼叫頻率,避免使用者惡意刷介面或者突發大流量導致服務不可用等,這邊記錄幾個常用的限流方法。

併發控制

簡單的併發控制,使用者的所有請求丟到乙個channel裡,再指定乙個帶緩衝區的channel為併發池,緩衝池的長度就是可以同時存在的協程數量,然後將執行完的任務根據需要直接返回或者丟到另外乙個channel 裡, 這樣做的問題是如果任務太多,後面的任務會慢慢等待(因為channel阻塞機制),使用者體驗不是太好。

}漏桶

簡單的限流,指定乙個大小固定的桶(bucket),以指定速率流入流出,如果桶滿了,則拒絕後續請求,好處是簡單,但是由於rate是固定的,導致了在無法在業務突發高峰時候(比如活動期間)有比較好的適配性。

)// 漏桶限流器

type bucketlimit struct

func newbucketlimit(rate float64, bucketsize int64) *bucketlimit

}func (b *bucketlimit) allowcontrol() bool

return false

}func main() else }}

令牌桶

令牌桶相比漏桶可以對突發的流量做一定程度的處理,該方法意思是一定速率往乙個桶裡放令牌(token),同時往桶裡注水,每消耗一滴水,需要一定數量的令牌,這裡**假設需要2塊令牌才能消耗1滴水,所以處理水滴的速度主要取決於令牌的數量。假設放入令牌的速度是4塊/s,每秒消耗的水滴數量是1滴,即每秒消耗2塊令牌,那麼每秒多出來的2塊令牌就會積累在桶裡,直到桶滿位置,然後因為某次活動大放水,每秒消耗的水滴數量突然變成了3滴,即每秒需要消耗6塊另外,大於每秒放入的令牌數量,由於之前桶裡有積累的令牌,所以即使放水量加大,依然可以在令牌桶消耗完之前快速處理。

// 令牌桶限流器

type bucketlimit struct

func newbucketlimit(rate float64, bucketsize int64) *bucketlimit

}func (b *bucketlimit) allowcontrol(tokenneed float64) bool else }

func main()

allow := limit.allowcontrol(19)

if allow else }}

他山之石

如果不自己造輪子,其實已經有很多別人造好的輪子,簡單記錄下,按需求選用:

偽**

import(

"fmt"

"net"

"golang.org/x/net/netutil")

func main()

defer l.close()

// 開啟限流, 其實就算是記錄器,max 就算最大的併發數量

}

後續**新增和更新就放這裡了:

redis benchmark 限流控制

由於自帶的redis benchmark不能按照設定的tps執行,因此增加tps控制功能。x t t tps 1 t x tps t 其中,x表示處理的請求數,t表示處理x筆請求花費的時間,t 表示需要等待的時間,tps表示設定的tps值利用redis benchmark中自帶的時間事件實現 int...

zuul限流控制

簡述 該包實現了在zuul對每個服務進行限流。提供的幾種限流方式 1.認證使用者 authenticated user 使用已認證的使用者名稱 username 或 anonymous 2.原始請求 request origin 使用使用者的原始請求 3.url 使用上游請求的位址 4.針對每個服務...

Golang 限流器 time rate 使用介紹

本主題為系列文章,分上下兩篇。本文主要介紹 time rate 的具體使用方法,另外一篇文章 golang 限流器 time rate 實現剖析 則著重介紹其內部實現原理。限流器是後台服務中的非常重要的元件,可以用來限制請求速率,保護服務,以免服務過載。限流器的實現方法有很多種,例如滑動視窗法 to...