日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

Go語言框架快速集成限流中間件詳解_Golang

作者:Masters ? 更新時間: 2022-11-01 編程語言

前言

在我們的日常開發(fā)中, 常用的中間件有很多, 今天來講一下怎么集成限流中間件, 它可以很好地用限制并發(fā)訪問數(shù)來保護(hù)系統(tǒng)服務(wù), 避免系統(tǒng)服務(wù)崩潰, 資源占用過大甚至服務(wù)器崩潰進(jìn)而影響到其他應(yīng)用!

分布式版

簡介

通常我們的服務(wù)會同時存在多個進(jìn)程, 也就是負(fù)載來保證服務(wù)的性能和穩(wěn)定性, 那么就需要走一個統(tǒng)一的限流, 這個時候就需要借助我們的老朋友-redis, 來進(jìn)行分布式限流;

算法

漏桶算法

即一個水桶, 進(jìn)水(接受請求)的速率不限, 出水(處理請求)的速率是一定的, 如果出水的速率小于進(jìn)水的速率, 就會造成水桶溢出(也就是拒絕請求); 主要是從出口限制, 以固定的速率控制訪問速度, 缺點(diǎn)是難以應(yīng)對突發(fā)請求;

實(shí)現(xiàn)

下面是一個簡單的實(shí)現(xiàn), 對 /v1/hello接口進(jìn)行每分鐘2次的速率限制

// RateLimitConf 速率配置, 允許多長時間通過多少次.
type RateLimitConf struct {
	Limit int64
	Timer time.Duration
}
// exampleLimiterMap 接口請求速率配置, 建議放入redis/數(shù)據(jù)庫同步本地緩存.
var exampleLimiterMap = map[string]RateLimitConf{
	"/v1/hello": {Limit: 2, Timer: time.Minute},
}
// LimiterMiddle 分布式限流中間件.
func LimiterMiddle(ctx iris.Context) {
	var (
		uri    = ctx.Request().RequestURI
		client = redis.NewClusterClient()
		key    = uri
	)
	conf, ok := exampleLimiterMap[uri]
	if ok {
		limiter := redis_rate.NewLimiter(client)
		if _, _, b := limiter.Allow(key, conf.Limit, conf.Timer); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

注意

  • 接口速率配置如果需要進(jìn)行實(shí)時配置, 則建議將配置寫入數(shù)據(jù)庫, 然后刷新到本地緩存/存到redis;
  • 如果需要對設(shè)備/ip/用戶進(jìn)行接口限制訪問, 則將 key加上唯一標(biāo)志即可;

單機(jī)版

簡介

這個就只適用于單個服務(wù)進(jìn)程的限流, 比如個人搭的一些小網(wǎng)站之類的;

算法

令牌桶算法

即也是一個桶, 按照設(shè)定的速率往桶里放令牌, 10s二十次即1s放兩個令牌(允許處理兩次請求), 然后請求來之后必須從桶里取出來令牌才可以進(jìn)行處理, 沒有令牌則選擇拒絕或等待; 主要是從入口限制, 允許一定量的突發(fā)請求(即桶內(nèi)所有的令牌);

依賴庫

golang.org/x/time/rate

實(shí)現(xiàn)

下面是一個簡單的實(shí)現(xiàn), 對 /v1/hello接口進(jìn)行每分鐘2次的速率限制

// exampleStandAloneLimiterMap 單機(jī)接口請求速率配置.
var exampleStandAloneLimiterMap = map[string]*rate.Limiter{
	"/v1/hello": rate.NewLimiter(rate.Every(time.Minute), 2),
}
// StandAloneLimiterMiddle 單機(jī)限流中間件.
func StandAloneLimiterMiddle(ctx iris.Context) {
	var (
		uri = ctx.Request().RequestURI
	)
	limiter, ok := exampleStandAloneLimiterMap[uri]
	if ok {
		if b := limiter.Allow(); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

結(jié)語

上面的代碼均摘自我開發(fā)的一個開源項(xiàng)目中, 主要是一個Go的標(biāo)準(zhǔn)項(xiàng)目布局, 封裝了一些常用的組件, 有興趣的朋友可以了解一下, 新手極易上手;

原文鏈接:https://juejin.cn/post/7140108558120517669

欄目分類
最近更新