当前位置:   article > 正文

gin中间件_gin限流器

gin限流器

一、ip限流器

1.借助使用golang 令牌桶,它可以指定桶的大小和每秒流进桶的个数。

  1. type Limiter struct {
  2. limiter rate.Limiter
  3. lastTime time.Time
  4. key string
  5. }
  6. func (l *Limiter) Allow() bool {
  7. return l.limiter.Allow()
  8. }

2.对不同的ip使用不同的限流器,将ip-limiter对存储到sync.map中

  1. type Limiters struct {
  2. limiters sync.Map
  3. }
  4. func NewLimiters() *Limiters {
  5. ls := &Limiters{}
  6. go ls.cleanLimiter()
  7. return ls
  8. }
  9. func (ls *Limiters) GetLimiter(key string, r rate.Limit, b int) *Limiter {
  10. if v, ok := ls.limiters.Load(key); ok {
  11. l := v.(*Limiter)
  12. l.lastTime = time.Now()
  13. return l
  14. }
  15. l := &Limiter{
  16. limiter: *rate.NewLimiter(r, b),
  17. lastTime: time.Now(),
  18. key: key,
  19. }
  20. ls.limiters.Store(key, l)
  21. return l
  22. }

3.同时对不再访问的限流器,应该定时的清除

  1. func (ls *Limiters) cleanLimiter() {
  2. ticker := time.NewTicker(time.Second * 10)
  3. defer ticker.Stop()
  4. for {
  5. <-ticker.C
  6. ls.limiters.Range(func(key, value interface{}) bool {
  7. l := value.(*Limiter)
  8. if time.Now().Sub(l.lastTime) > time.Minute {
  9. ls.limiters.Delete(key)
  10. }
  11. return true
  12. })
  13. }
  14. }

4.构建中间件:每个IP只能每秒访问一次。

  1. var limiters = NewLimiters()
  2. func LimitMiddleWare(ctx *gin.Context) {
  3. ip := ctx.RemoteIP()
  4. l := limiters.GetLimiter(ip, rate.Limit(1), 1)
  5. if !l.Allow() {
  6. ctx.Status(http.StatusTooManyRequests)
  7. ctx.Abort()
  8. }
  9. }

5.测试:将中间件放在全局。当然也可以放在一个路由上或一个路由组上

  1. func main() {
  2. en := gin.New()
  3. en.Use(middleware.LimitMiddleWare)
  4. en.GET("/index", func(ctx *gin.Context) {
  5. ctx.String(200, "index")
  6. })
  7. en.Run(":8080")
  8. }

快速请求两次,第二次被拦截!

二、崩溃recover器

1.recover必须在defer中执行。将debug.Stack()写入文件中。

  1. func MyRecover() gin.HandlerFunc {
  2. return func(c *gin.Context) {
  3. defer func() {
  4. if e := recover(); e != nil {
  5. pwd, _ := os.Getwd()
  6. fd, e2 := os.Create(pwd + "/" + time.Now().Format("20060102030405") + ".stack")
  7. if e2 == nil && fd != nil {
  8. e3, ok := e.(error)
  9. if ok {
  10. fd.WriteString("recover:" + e3.(error).Error() + "\n")
  11. }
  12. fd.Write(debug.Stack())
  13. fd.Close()
  14. } else {
  15. log.Println("error:", e, e2)
  16. log.Println("error:", string(debug.Stack()))
  17. }
  18. }
  19. }()
  20. c.Next() // 调用下一个处理
  21. }
  22. }

三、JWT认证

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/724374
推荐阅读
相关标签
  

闽ICP备14008679号