Golang實現ip限流
隨著網路和行動網路的快速發展,伺服器面對的壓力越來越大,如何限制客戶端對伺服器的請求,避免伺服器崩潰成為了一個大問題。在實際專案中,我們經常需要限制IP的請求數,保證網站的可用性。
在這裡,我們將介紹如何使用Golang實作IP限流。總的來說,我們將利用令牌桶演算法來實現基於IP位址的限流。令牌桶演算法是一種流量控制演算法,它允許一定數量的請求在一定時間內通過並限制一段時間內的請求流量。
實現細節
令牌桶演算法以恆定速率往桶中放入令牌,令牌桶有一個容量限制,表示桶中的令牌數量不會超過容量。對於每個請求,從桶中移除一個令牌,如果桶中沒有令牌,則請求無法通過。
為了實現基於IP位址的限流,我們需要為每個IP位址建立一個令牌桶,每個令牌桶都有一個最大容量和一個恆定的速度。當請求到來時,我們從令牌桶中移除一個令牌,如果桶中沒有令牌,則拒絕請求。
基於此,我們可以定義一個IP限流器:
type IPRateLimiter struct { limiterBuckets map[string]*rate.Limiter mu *sync.Mutex r rate.Limit b int }
其中,limiterBuckets 是一個映射,將字串 IP 位址映射到令牌桶。 mu 是互斥鎖, r 是速率限制器每秒放入令牌的速率, b 是令牌桶的容量。
為了為每個IP位址建立令牌桶,我們定義一個函數NewIPRateLimiter :
func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter { return &IPRateLimiter{ limiterBuckets: make(map[string]*rate.Limiter), mu: &sync.Mutex{}, r: r, b: b, } } func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter { i.mu.Lock() defer i.mu.Unlock() limiter := rate.NewLimiter(i.r, i.b) i.limiterBuckets[ip] = limiter return limiter }
AddIP函數用於為IP位址建立令牌桶。如果為該IP位址建立了令牌桶,則傳回現有的令牌桶,否則建立一個新的令牌桶並傳回。
最後,我們可以實作HTTP中間件來限制IP位址的請求數:
func (i *IPRateLimiter) Limit(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ip := r.RemoteAddr limiter, ok := i.limiterBuckets[ip] if !ok { limiter = i.AddIP(ip) } if !limiter.Allow() { http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests) return } next.ServeHTTP(w, r) }) }
該中間件允許在指定的速率和容量下通過請求。如果請求數超過容量,則傳回HTTP錯誤代碼429(太多請求)。
完整程式碼如下:
package main import ( "net/http" "strconv" "sync" "golang.org/x/time/rate" ) type IPRateLimiter struct { limiterBuckets map[string]*rate.Limiter mu *sync.Mutex r rate.Limit b int } func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter { return &IPRateLimiter{ limiterBuckets: make(map[string]*rate.Limiter), mu: &sync.Mutex{}, r: r, b: b, } } func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter { i.mu.Lock() defer i.mu.Unlock() limiter := rate.NewLimiter(i.r, i.b) i.limiterBuckets[ip] = limiter return limiter } func (i *IPRateLimiter) Limit(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ip := r.RemoteAddr limiter, ok := i.limiterBuckets[ip] if !ok { limiter = i.AddIP(ip) } if !limiter.Allow() { http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests) return } next.ServeHTTP(w, r) }) } func IndexHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("welcome.")) } func main() { limit := rate.Limit(10) // 速率,每秒放入令牌的数量 capacity := 100 // 容量,桶的大小 ipRateLimiter := NewIPRateLimiter(limit, capacity) http.Handle("/", ipRateLimiter.Limit(http.HandlerFunc(IndexHandler))) err := http.ListenAndServe(":8080", nil) if err != nil { panic(err) } }
在這個例子中,我們允許每秒放入10個令牌,並限製桶的容量為100。這表示此限制器可以處理每秒最多10個請求,但如果對相同IP位址的請求達到100個,則無法通過請求。同時,我們定義了一個簡單的處理程序,它將回應「歡迎」。
結論
在本文中,我們使用Golang實作了IP限流,採用令牌桶演算法來限制每個IP位址的請求速率。這種方法可以實作一個簡單而有效的限流機制,並且可以在Golang中方便地實作。當你在編寫高並發的網頁應用程式時,這可能是一個非常有用的技巧。
以上是Golang實現ip限流的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

OpenSSL,作為廣泛應用於安全通信的開源庫,提供了加密算法、密鑰和證書管理等功能。然而,其歷史版本中存在一些已知安全漏洞,其中一些危害極大。本文將重點介紹Debian系統中OpenSSL的常見漏洞及應對措施。 DebianOpenSSL已知漏洞:OpenSSL曾出現過多個嚴重漏洞,例如:心臟出血漏洞(CVE-2014-0160):該漏洞影響OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻擊者可利用此漏洞未經授權讀取服務器上的敏感信息,包括加密密鑰等。

後端學習路徑:從前端轉型到後端的探索之旅作為一名從前端開發轉型的後端初學者,你已經有了nodejs的基礎,...

在BeegoORM框架下,如何指定模型關聯的數據庫?許多Beego項目需要同時操作多個數據庫。當使用Beego...

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

Go語言中字符串打印的區別:使用Println與string()函數的效果差異在Go...
