1. 程式人生 > 實用技巧 >golang gin框架中實現一個簡單的不是特別精確的秒級限流器

golang gin框架中實現一個簡單的不是特別精確的秒級限流器

起因

看了兩篇關於golang中限流器的帖子:

我照著用,居然沒效果……

時間有限沒有深究。這實在是一個很簡單的功能,我的需求是每分鐘限制大約xxx次請求,平均每秒限制到XXX除60次左右的請求也就夠了。

限流器程式碼

於是下面用了個及其簡單的方式來實現限流器:
utils/limiter.go

package utils

import (
	"sync/atomic"
	"time"
)

//Limiter 限流器物件
type Limiter struct {
	value  int64
	max    int64
	ts     int64
}

//NewLimiter 產生一個限流器
func NewLimiter(cnt int64) *Limiter {
	return &Limiter{
		value:  0,
		max:    cnt,
		ts:     time.Now().Unix(),
	}
}

//Ok 是否可以通過
func (l *Limiter) Ok() bool {
	ts := time.Now().Unix()
	tsOld := atomic.LoadInt64(&l.ts)
	if ts != tsOld {
		atomic.StoreInt64(&l.ts, ts)
		atomic.StoreInt64(&l.value, 1)
		return true
	}
	return atomic.AddInt64(&(l.value), 1) < l.max
}

//SetMax 設定最大限制
func (l *Limiter) SetMax(m int64) {
	l.max = m
}

gin框架中使用

main.go

//MaxAllowed 限流器
func MaxAllowed(limitValue int64) func(c *gin.Context) {
	limiter := utils.NewLimiter(limitValue)
	log.Println("limiter.SetMax:", limitValue)
	// 返回限流邏輯
	return func(c *gin.Context) {
		if !limiter.Ok() {
			c.AbortWithStatus(http.StatusServiceUnavailable)  //超過每秒200,就返回503錯誤碼
			return
		}
		c.Next()
	}
}

func main(){
    router := gin.New()
    router.Use(MaxAllowed(200))  //限制每秒最多允許200個請求
}

have fun!