• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

0x1cc4

Youth means limitless possibilities. 年轻就是无限的可能。
  • 订阅
  • 管理

公告

View Post

Go+Gin 接口防止用户频繁访问

在Go+Gin框架中,可以利用中间件实现API防洪(防止用户频繁访问)功能。一种常见的防洪技术是利用Go的漏桶算法或令牌桶算法进行流量控制。
以下面的Go代码为例,演示了一个简单的令牌桶方式的中间件:

package main

import (
    "net/http"
    "time"

    "github.com/gin-gonic/gin"
    "golang.org/x/time/rate"
)

// 创建一个 map 来存储每个 IP 的访问限制
var visitors = make(map[string]*rate.Limiter)

// 获取用户 IP 为 key 的令牌桶,若不存在则创建一个
func getVisitor(ip string) *rate.Limiter {
    limiter, exists := visitors[ip]
    if !exists {
        limiter = rate.NewLimiter(1, 5)  // 每秒生成1个令牌,且桶中最多存储5个令牌
        visitors[ip] = limiter
    }

    return limiter
}

// 控制访问频率的中间件
func limitMiddleware(c *gin.Context) {
    limiter := getVisitor(c.ClientIP())
    // Allow方法返回是否可以接收请求,此处是否可以拿取令牌
    if !limiter.Allow() {
        c.String(http.StatusTooManyRequests, "Too many requests.")
        c.Abort()
        return
    }

    c.Next()
}

func main() {
    router := gin.Default()
    router.Use(limitMiddleware)

    router.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Welcome!")
    })

    router.Run(":8080")
}

因为此方式是在内存中存储IP与限制器映射的,重启服务后计数器将被重置,且长时间大量请求可能会耗费更多内存。如果想要更加稳健的处理方式,可以考虑使用Redis等数据库存储限制器。同时真实环境中,用户的IP可能会被隐藏或者动态更换,所以光靠IP可能无法完全限制某一用户的访问频率,具体情况需要具体分析。
注意,运行此代码需要额外安装 "golang.org/x/time/rate" 包。你可以通过 "go get golang.org/x/time/rate" 获取这个包。

本文来自博客园,作者:0x1cc4,转载请注明原文链接:https://www.cnblogs.com/0x1cc4/p/18087675

posted on 2024-03-21 16:26  0x1cc4  阅读(360)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3