golang ratelimit限流实现

网上找到的案例,记录一下

route/init方法中:

var uriLimiters = middleware.NewUriLimiter()
appGroup := g.Group("", middleware.RateLimiter(uriLimiters))

//限流
func RateLimiter(l LimiterIface) gin.HandlerFunc {
return func(c *gin.Context) {
key := l.Key(c) + c.ClientIP()
if bucket, ok := l.GetBucket(key); ok {
count := bucket.TakeAvailable(1)
if count == 0 {
return
}
} else {
l.AddBucketsByUri(key, 3, 100, 100)
c.Next()
}
c.Next()
}
}


中间件具体代码
package middleware

import (
"github.com/gin-gonic/gin"
"github.com/juju/ratelimit"
"strings"
"time"
)

type LimitConfRules struct {
Rules map[string]*LimitOpt `mapstructure:"rules"`
}

type LimitOpt struct {
Interval int64 `mapstructure:"interval"`
Capacity int64 `mapstructure:"capacity"`
Quantum int64 `mapstructure:"quantum"`
}

type LimiterIface interface {
Key(c *gin.Context) string
GetBucket(key string) (*ratelimit.Bucket, bool)
AddBucketsByUri(uri string, fillInterval, capacity, quantum int64) LimiterIface
AddBucketByConf() LimiterIface
}

type Limiter struct {
limiterBuckets map[string]*ratelimit.Bucket
}

type UriLimiter struct {
*Limiter
Rule *LimitConfRules
}

func NewUriLimiter() LimiterIface {
return &UriLimiter{
Limiter: &Limiter{
limiterBuckets: make(map[string]*ratelimit.Bucket),
},
}
}

func (l *UriLimiter) Key(c *gin.Context) string {
uri := c.Request.RequestURI
index := strings.Index(uri, "?")
if index == -1 {
return uri
}
return uri[:index]
}

func (l *UriLimiter) GetBucket(key string) (*ratelimit.Bucket, bool) {
bucket, ok := l.limiterBuckets[key]
return bucket, ok
}

func (l *UriLimiter) AddBucketsByUri(uri string, fillInterval, capacity, quantum int64) LimiterIface {
bucket := ratelimit.NewBucketWithQuantum(time.Second*time.Duration(fillInterval), capacity, quantum)
l.limiterBuckets[uri] = bucket
return l
}

func (l *UriLimiter) getConf() *LimitConfRules {

rule := &LimitConfRules{Rules: map[string]*LimitOpt{
"/": {
Interval: 10, //多长时间添加令牌
Capacity: 1, //令牌桶的容量
Quantum: 1, //到达定时器指定的时间,往桶里面加多少令牌
},
}}

return rule
}

func (l *UriLimiter) AddBucketByConf() LimiterIface {
rule := l.getConf()
for k, v := range rule.Rules {
l.AddBucketsByUri(k, v.Interval, v.Capacity, v.Quantum)
}
return l
}

posted on   studyphp  阅读(377)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2019-11-14 Vue 定义全局变量
2019-11-14 vue 配置CDN加速

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示