欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang編寫自定義IP限流中間件的方法詳解

 更新時(shí)間:2023年09月18日 09:21:51   作者:小小小熊貓5  
這篇文章給大家詳細(xì)的介紹了Golang編寫自定義IP限流中間件的方法,文章通過代碼實(shí)例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

基于令牌桶的限流算法

  • r:每秒鐘向桶內(nèi)放入 r 個(gè)令牌,即每隔 1/r秒放一個(gè)令牌
  • b:桶的最大容量是 b,桶滿后試圖再放入的令牌會(huì)被丟棄掉
  • 當(dāng)有人請(qǐng)求 n 個(gè)令牌時(shí),如果桶中的令牌數(shù)小于n,則請(qǐng)求放阻塞或直接放棄,否則順利從桶中取走 n 個(gè)令牌
    • 當(dāng) b > 1 時(shí),任意 1/r 秒內(nèi)最多可以取走 b 個(gè)令牌
      • 限制很短的一個(gè)瞬間的一個(gè)最高的并發(fā)量,b=最高的并發(fā)量,r=最短的時(shí)間段
    • 當(dāng) b = 1 時(shí),每秒鐘最多可被取走 r 個(gè)令牌
      • 限制每秒鐘的最高的QPS:b=1,r=最高的QPS
      • 限制每分鐘的最高請(qǐng)求量:把每分鐘的請(qǐng)求量/60=轉(zhuǎn)換成1秒鐘,賦給 r 就可以了
      • 限制每5分鐘、每10分鐘,同理

實(shí)現(xiàn)高并發(fā)限流(使用golang官方限流器)

Go代碼

源碼地址: GitHub-golang版本

middleware/rateLimiterMiddleware.go

package middleware
import (
	"net/http"
	"time"
	"github.com/gin-gonic/gin"
	"golang.org/x/time/rate"
)
var Limiter *rate.Limiter
// 定義一個(gè)中間件函數(shù)來進(jìn)行限流
func RateLimiterMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		if !Limiter.AllowN(time.Now(), 1) {
			c.JSON(http.StatusTooManyRequests, gin.H{"message": "Rate limit exceeded"})
			// 設(shè)置休眠和業(yè)務(wù)時(shí)長(zhǎng)一樣,為了更好從日志出看出規(guī)則
			time.Sleep(50 * time.Millisecond)
			c.Abort()
			return
		}
		c.Next()
	}
}

main.go

func main() {
	r := gin.Default()
	// 創(chuàng)建一個(gè)限流器,每秒允許最多10個(gè)請(qǐng)求
	middleware.Limiter = rate.NewLimiter(rate.Limit(10), 1)
	// 使用限流中間件
	r.Use(middleware.RateLimiterMiddleware())
	r.GET("/api/resource", func(c *gin.Context) {
		time.Sleep(50 * time.Millisecond)
		c.JSON(http.StatusOK, gin.H{"message": "Resource accessed"})
	})
	r.Run(":8080")
}

測(cè)試記錄

ab -t 1 -c 1 http://127.0.0.1:8080/api/resource

使用ab壓力測(cè)試,并發(fā)量為1的(相當(dāng)于串行),在1秒內(nèi)不斷發(fā)出請(qǐng)求(算下來,每個(gè)請(qǐng)求50ms,總共能發(fā)出20個(gè)請(qǐng)求)

結(jié)果預(yù)測(cè):1秒內(nèi)最多生成10個(gè)令牌,而總共有20個(gè)串行的請(qǐng)求,結(jié)果應(yīng)該是1個(gè)成功(在50ms結(jié)束),1個(gè)失?。ê?0ms內(nèi)還未有新的令牌生成),1個(gè)成功,1個(gè)失敗。。。 結(jié)果輸出(符合預(yù)期)

在這里插入圖片描述

在這里插入圖片描述

升級(jí):根據(jù)每個(gè)IP地址進(jìn)行限流

Go代碼

源碼地址: GitHub-golang版本

middleware/ipRateLimiterMiddleware.go

package middleware
import (
	"net/http"
	"sync"
	"time"
	"github.com/gin-gonic/gin"
	"golang.org/x/time/rate"
)
var IPLimiter *IPRateLimiter
func NewIPRateLimiter() *IPRateLimiter {
	return &IPRateLimiter{
		limiter: make(map[string]*rate.Limiter),
	}
}
type IPRateLimiter struct {
	mu      sync.Mutex
	limiter map[string]*rate.Limiter
}
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
	i.mu.Lock()
	defer i.mu.Unlock()
	limiter, exists := i.limiter[ip]
	if !exists {
		limiter = rate.NewLimiter(2, 5) // 每秒2個(gè)請(qǐng)求,桶容量為5
		i.limiter[ip] = limiter
	}
	return limiter
}
// 定義一個(gè)中間件函數(shù)來進(jìn)行限流
func IPRateLimiterMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		ip := c.ClientIP()
		limiter := IPLimiter.GetLimiter(ip)
		if !limiter.Allow() {
			c.JSON(http.StatusTooManyRequests, gin.H{"message": "Rate limit exceeded"})
			// 設(shè)置休眠和業(yè)務(wù)時(shí)長(zhǎng)一樣,為了更好從日志出看出規(guī)則
			time.Sleep(50 * time.Millisecond)
			c.Abort()
			return
		}
		c.Next()
	}
}

main.go

func main() {
	r := gin.Default()
	// 創(chuàng)建IP限流器
	middleware.IPLimiter = middleware.NewIPRateLimiter()
	// 使用限流中間件
	r.Use(middleware.IPRateLimiterMiddleware())
	r.GET("/api/resource", func(c *gin.Context) {
		time.Sleep(50 * time.Millisecond)
		c.JSON(http.StatusOK, gin.H{"message": "Resource accessed"})
	})
	r.Run(":8080")
}

測(cè)試記錄

ab -t 1 -c 1 http://127.0.0.1:8080/api/resource

使用ab壓力測(cè)試,并發(fā)量為1的(相當(dāng)于串行),在1秒內(nèi)不斷發(fā)出請(qǐng)求(算下來,每個(gè)請(qǐng)求50ms,總共能發(fā)出20個(gè)請(qǐng)求)

結(jié)果預(yù)測(cè):1秒內(nèi)最多生成2個(gè)令牌,桶容量為5 代表在1/2秒內(nèi)的最大并發(fā)量是5,總共有20個(gè)串行的請(qǐng)求,結(jié)果應(yīng)該是先成功5個(gè)(桶容量全使用成功), 之后剩余成功的是1個(gè),其余全部失敗

  • 當(dāng)程序啟動(dòng)時(shí),限流器初始化,桶是空的,沒有令牌。
  • 在每秒的前兩次令牌生成中,每次生成2個(gè)令牌,并放入桶中。
  • 在第3秒,生成的2個(gè)令牌中只有1個(gè)能夠被放入桶中,因?yàn)橥耙呀?jīng)滿了。
  • 當(dāng)使用ab發(fā)出請(qǐng)求時(shí),前5個(gè)請(qǐng)求依次拿到了令牌并成功,每個(gè)請(qǐng)求耗時(shí)50ms。此時(shí)總耗時(shí)為250ms。
  • 第6個(gè)請(qǐng)求在300ms,第7個(gè)請(qǐng)求在350ms,第8個(gè)請(qǐng)求在400ms,第9個(gè)請(qǐng)求在450ms,第10個(gè)請(qǐng)求在500ms。
  • 因?yàn)橄蘖髌鞯乃俾适敲棵?個(gè)請(qǐng)求,也就是每500ms生成一個(gè)令牌。 第500ms時(shí)新的令牌生成,所以第6-10請(qǐng)求期間,是沒有令牌的,所以都請(qǐng)求失敗,而11個(gè)請(qǐng)求時(shí)有新令牌生成,所以能成功。
  • 之后的請(qǐng)求以此類推,需要等待新令牌生成。

結(jié)果輸出(符合預(yù)期)

在這里插入圖片描述

在這里插入圖片描述

以上就是Golang編寫自定義IP限流中間件的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Golang編寫IP限流中間件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹

    golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹

    這篇文章主要介紹了golang 結(jié)構(gòu)體初始化時(shí)賦值格式介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 詳解Go并發(fā)編程時(shí)如何避免發(fā)生競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)

    詳解Go并發(fā)編程時(shí)如何避免發(fā)生競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)

    大家都知道,Go是一種支持并發(fā)編程的編程語言,但并發(fā)編程也是比較復(fù)雜和容易出錯(cuò)的。比如本篇分享的問題:競(jìng)態(tài)條件和數(shù)據(jù)競(jìng)爭(zhēng)的問題
    2023-04-04
  • 細(xì)說Go語言中空結(jié)構(gòu)體的奇妙用途

    細(xì)說Go語言中空結(jié)構(gòu)體的奇妙用途

    Go語言中,我們可以定義空結(jié)構(gòu)體,即沒有任何成員變量的結(jié)構(gòu)體,使用關(guān)鍵字?struct{}?來表示。這種結(jié)構(gòu)體似乎沒有任何用處,但實(shí)際上它在?Go?語言中的應(yīng)用非常廣泛,本文就來詳解講講
    2023-05-05
  • Go?的入口函數(shù)和包初始化的使用

    Go?的入口函數(shù)和包初始化的使用

    本文主要介紹了Go?的入口函數(shù)和包初始化的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 基于Go語言實(shí)現(xiàn)猜謎游戲

    基于Go語言實(shí)現(xiàn)猜謎游戲

    這篇文章主要為大家詳細(xì)介紹了如何基于Go語言實(shí)現(xiàn)猜謎游戲,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)
    2023-09-09
  • Go 防止 goroutine 泄露的方法

    Go 防止 goroutine 泄露的方法

    Go 的并發(fā)模型與其他語言不同,雖說它簡(jiǎn)化了并發(fā)程序的開發(fā)難度,但如果不了解使用方法,常常會(huì)遇到 goroutine 泄露的問題。本篇主要從如何寫出正確代碼的角度來介紹如何防止 goroutine 的泄露,需要的朋友可以參考下
    2019-09-09
  • Go實(shí)現(xiàn)數(shù)據(jù)脫敏的方案設(shè)計(jì)

    Go實(shí)現(xiàn)數(shù)據(jù)脫敏的方案設(shè)計(jì)

    在一些常見的業(yè)務(wù)場(chǎng)景中可能涉及到用戶的手機(jī)號(hào),銀行卡號(hào)等敏感數(shù)據(jù),對(duì)于這部分的數(shù)據(jù)經(jīng)常需要進(jìn)行數(shù)據(jù)脫敏處理,就是將此部分?jǐn)?shù)據(jù)隱私化,防止數(shù)據(jù)泄露,所以本文給大家介紹了Go實(shí)現(xiàn)數(shù)據(jù)脫敏的方案設(shè)計(jì),需要的朋友可以參考下
    2024-05-05
  • Golang迭代如何在Go中循環(huán)數(shù)據(jù)結(jié)構(gòu)使用詳解

    Golang迭代如何在Go中循環(huán)數(shù)據(jù)結(jié)構(gòu)使用詳解

    這篇文章主要為大家介紹了Golang迭代之如何在Go中循環(huán)數(shù)據(jù)結(jié)構(gòu)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Go代碼檢查的推薦工具及使用詳解

    Go代碼檢查的推薦工具及使用詳解

    這篇文章主要為大家介紹了Go代碼檢查的推薦工具及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Go結(jié)合JavaScript實(shí)現(xiàn)抓取網(wǎng)頁中的圖像鏈接

    Go結(jié)合JavaScript實(shí)現(xiàn)抓取網(wǎng)頁中的圖像鏈接

    這篇文章主要為大家詳細(xì)介紹了Go語言如何結(jié)合JavaScript實(shí)現(xiàn)抓取網(wǎng)頁中的圖像鏈接,文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11

最新評(píng)論