首页 > 其他分享 >golang ratelimit限流实现

golang ratelimit限流实现

时间:2022-11-14 14:01:33浏览次数:43  
标签:return string golang ratelimit 限流 func LimiterIface UriLimiter

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

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
}

标签:return,string,golang,ratelimit,限流,func,LimiterIface,UriLimiter
From: https://www.cnblogs.com/already/p/16888823.html

相关文章

  • golang redis队列实现
    记录一下packageredisimport("bytes""encoding/json""errors")typeJobstruct{JobIdstring`json:"job_id"`Uiduint64`json:"uid"`......
  • golang处理时区
    很多Golang初学者都不知道怎么来处理时区问题.这篇文章将解释清楚一下两个问题:怎么把带时区的时间保存到数据库?在Go语言中怎么解析带时区的时间?1.数据库时区(Time......
  • golang fmt && lint
    如何轻松使用格式化和静态检查工具makefmtmakelint 1、go.mod同级目录创建文件Makefilefmt:command-vgofumpt||(WORK=$(shellpwd)&&cd/tmp&&......
  • golang内存对齐的重要性
     结构体中字段类型的改变直接造成内存对齐结果的改变,是的占用内存空间也不一样packagemainimport( "fmt" "unsafe")funcmain(){ varxxstruct{ aboo......
  • golang:break,continue,return,goto使用区别
    break条件满足,跳出整个循环continue条件满足,跳出这次循环,但继续执行后面的循环return返回数据,结束当前函数或程序运行gotogo语言的goto可以无条件的转移到程序中指......
  • Golang:error包错误处理
    (目录)1、Golangerror包内建error接口//builtin.gotypeerrorinterface{Error()string}实现error接口//errors.gopackageerrorstypeerrorStrings......
  • Golang结构体方法和接收者
    结构体方法和接收者在go语言中,没有累的概念,但是可以给类型(结构体,自定义类型)定义方法。所谓方法就是定义了接收者的函数。接收者的概念就类似于其它语言中的this或者self。......
  • python调用golang 从指定序列中找出一组与目标值最接近的子序列 kayb
    python调用golang从指定序列中找出一组与目标值最接近的子序列编写go代码生成so库python代码调用编写go代码写入hello.go文件packagemainimport( "C" "en......
  • golang操作文件或者目录
    使用golang操作文件和目录Go&Rust......
  • golang echo group 用法的微妙注意点
    用不好的话,可能会引发很诡异的问题。packagemainimport( "net/http" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/si......