赞
踩
1.借助使用golang 令牌桶,它可以指定桶的大小和每秒流进桶的个数。
-
- type Limiter struct {
- limiter rate.Limiter
- lastTime time.Time
- key string
- }
-
- func (l *Limiter) Allow() bool {
- return l.limiter.Allow()
- }
2.对不同的ip使用不同的限流器,将ip-limiter对存储到sync.map中
- type Limiters struct {
- limiters sync.Map
- }
-
- func NewLimiters() *Limiters {
- ls := &Limiters{}
- go ls.cleanLimiter()
- return ls
- }
-
- func (ls *Limiters) GetLimiter(key string, r rate.Limit, b int) *Limiter {
- if v, ok := ls.limiters.Load(key); ok {
- l := v.(*Limiter)
- l.lastTime = time.Now()
- return l
- }
- l := &Limiter{
- limiter: *rate.NewLimiter(r, b),
- lastTime: time.Now(),
- key: key,
- }
- ls.limiters.Store(key, l)
- return l
- }
3.同时对不再访问的限流器,应该定时的清除
- func (ls *Limiters) cleanLimiter() {
- ticker := time.NewTicker(time.Second * 10)
- defer ticker.Stop()
- for {
- <-ticker.C
- ls.limiters.Range(func(key, value interface{}) bool {
- l := value.(*Limiter)
- if time.Now().Sub(l.lastTime) > time.Minute {
- ls.limiters.Delete(key)
- }
- return true
- })
- }
- }
4.构建中间件:每个IP只能每秒访问一次。
- var limiters = NewLimiters()
-
- func LimitMiddleWare(ctx *gin.Context) {
- ip := ctx.RemoteIP()
- l := limiters.GetLimiter(ip, rate.Limit(1), 1)
- if !l.Allow() {
- ctx.Status(http.StatusTooManyRequests)
- ctx.Abort()
- }
- }
5.测试:将中间件放在全局。当然也可以放在一个路由上或一个路由组上。
- func main() {
- en := gin.New()
- en.Use(middleware.LimitMiddleWare)
-
- en.GET("/index", func(ctx *gin.Context) {
- ctx.String(200, "index")
- })
-
- en.Run(":8080")
- }
快速请求两次,第二次被拦截!
1.recover必须在defer中执行。将debug.Stack()写入文件中。
- func MyRecover() gin.HandlerFunc {
- return func(c *gin.Context) {
- defer func() {
- if e := recover(); e != nil {
- pwd, _ := os.Getwd()
- fd, e2 := os.Create(pwd + "/" + time.Now().Format("20060102030405") + ".stack")
- if e2 == nil && fd != nil {
- e3, ok := e.(error)
- if ok {
- fd.WriteString("recover:" + e3.(error).Error() + "\n")
- }
- fd.Write(debug.Stack())
- fd.Close()
- } else {
- log.Println("error:", e, e2)
- log.Println("error:", string(debug.Stack()))
- }
- }
- }()
- c.Next() // 调用下一个处理
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。