基于Gin框架的HTTP接口限速实践
在当今的微服务架构和RESTful API主导的时代,HTTP接口在各个业务模块之间扮演着重要的角色。随着业务规模的不断扩大,接口的访问频率和负载也随之增加。为了确保系统的稳定性和性能,接口限速成了一个重要的话题。
1 接口限速的使用场景
接口限速的使用场景主要涉及以下几种情况:
- 防止API滥用:在某些情况下,如果没有有效的限速机制,恶意用户可能会无限制地调用API,导致系统过载。通过接口限速,我们可以限制每个用户对特定接口的访问频率,从而防止API滥用。
- 保护服务稳定性:在某些情况下,某些高频调用可能会给后端服务带来巨大的压力,影响服务的稳定性和性能。通过接口限速,我们可以限制对这些接口的访问频率,从而保护服务的稳定性。
- 资源合理分配:在一些情况下,我们需要对系统资源进行合理的分配,确保每个用户都能得到公平的资源使用。通过接口限速,我们可以根据用户的请求频率进行资源分配,从而保证公平性。
2 限速不同与限流
接口限速和限流是两个不同的概念,虽然它们都是用来控制流量和保护系统的手段,但它们的目的和实现方式有所不同。
**接口限速主要是限制接口的访问速度,避免过快的请求频率对系统造成压力。**它关注的是单个接口的访问速率,比如每秒可以访问多少次,而限流则是关注系统的整体流量,限制单位时间内系统的总访问量。
限速通常是通过在接口上设置速率限制来实现的,例如使用令牌桶算法或漏桶算法等。它的主要目的是防止单个接口的过快访问,以保护系统的稳定性和性能。
**而限流则是通过一系列机制来限制单位时间内系统的总访问量,以防止系统过载。**常见的限流算法包括令牌桶算法、漏桶算法和热点参数等。它的主要目的是保护整个系统,避免因为访问量过大而出现崩溃或性能下降的情况。
在实现方面,限速通常是在应用程序或API网关层面实现的,而限流则可能需要涉及到整个系统的架构和设计。
虽然接口限速和限流的目的和实现方式有所不同,但它们都是为了控制流量和保护系统的稳定性和性能。在实际应用中,我们可以根据实际情况选择合适的限速和限流策略,以实现最佳的流量控制效果。
3 Gin框架接口限速实践
基于limiter插件的GitHub地址:github.com/ulule/limiter
3.1 基本使用
package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin""github.com/redis/go-redis/v9""github.com/ulule/limiter/v3"mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)func main() {// Define a limit rate to 4 requests per hour.rate, err := limiter.NewRateFromFormatted("4-M")if err != nil {log.Fatal(err)return}// Create a redis client.option, err := redis.ParseURL("redis://localhost:6379/0")if err != nil {log.Fatal(err)return}client := redis.NewClient(option)// Create a store with the redis client.store, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example",MaxRetry: 3,})if err != nil {log.Fatal(err)return}// Create a new middleware with the limiter instance.middleware := mgin.NewMiddleware(limiter.New(store, rate))// Launch a simple server.router := gin.Default()router.ForwardedByClientIP = truerouter.Use(middleware)router.GET("/", index)log.Fatal(router.Run(":8081"))
}func index(c *gin.Context) {c.JSON(http.StatusOK, "This is my gin api...")
}
3.2 引入自定义拦截处理器
package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin""github.com/redis/go-redis/v9""github.com/ulule/limiter/v3"mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)func main() {rate, err := limiter.NewRateFromFormatted("4-M")if err != nil {log.Fatal(err)return}option, err := redis.ParseURL("redis://localhost:6379/0")if err != nil {log.Fatal(err)return}client := redis.NewClient(option)store, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example",MaxRetry: 3,})if err != nil {log.Fatal(err)return}//自定义拦截处理器opt := mgin.WithLimitReachedHandler(ExceededHandler)middleware := mgin.NewMiddleware(limiter.New(store, rate), opt)router := gin.Default()router.ForwardedByClientIP = truerouter.Use(middleware)router.GET("/", index)log.Fatal(router.Run(":8081"))
}func ExceededHandler(c *gin.Context) {c.JSON(200, "This is mu custom ExceededHandler...")
}func index(c *gin.Context) {c.JSON(http.StatusOK, "This is my gin api...")
}
返回结果:
3.3 不同接口区分速率
我们假设系统有两个接口:
- /fast : 每分钟允许10次访问
- /slow : 每分钟允许1次访问
代码实现:
package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin""github.com/redis/go-redis/v9""github.com/ulule/limiter/v3"mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)var (fastTime = 0slowTime = 0
)func FastApi(c *gin.Context) {fastTime += 1c.JSON(200, fmt.Sprintf("This is fast api... %d", fastTime))
}func SlowApi(c *gin.Context) {slowTime += 1c.JSON(200, fmt.Sprintf("This is slow api... %d", slowTime))
}func main() {fastRate, err := limiter.NewRateFromFormatted("10-M")if err != nil {log.Fatal(err)return}slowRate, err := limiter.NewRateFromFormatted("1-M")if err != nil {log.Fatal(err)return}option, err := redis.ParseURL("redis://localhost:6379/0")if err != nil {log.Fatal(err)return}client := redis.NewClient(option)storeFast, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example_fast", MaxRetry: 3})if err != nil {log.Fatal(err)return}storeSlow, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example_slow", MaxRetry: 3})if err != nil {log.Fatal(err)return}//自定义拦截处理器opt := mgin.WithLimitReachedHandler(ExceededHandler)middlewareFast := mgin.NewMiddleware(limiter.New(storeFast, fastRate), opt)middlewareSlow := mgin.NewMiddleware(limiter.New(storeSlow, slowRate), opt)router := gin.Default()router.ForwardedByClientIP = truerouter.Use(func(c *gin.Context) {if c.Request.RequestURI == "/fast" {middlewareFast(c)return}if c.Request.RequestURI == "/slow" {middlewareSlow(c)return}})router.GET("/fast", FastApi)router.GET("/slow", SlowApi)log.Fatal(router.Run(":8081"))
}func ExceededHandler(c *gin.Context) {c.JSON(200, "This is mu custom ExceededHandler...")
}
4 小总结
接口限速是保护系统稳定性和API的重要手段。在实际应用中,我们需要根据实际情况选择合适的限速方法,实现对接口的全面限速。通过接口限速,我们可以提高系统的稳定性、保护API、提高用户体验等。
相关文章:

基于Gin框架的HTTP接口限速实践
在当今的微服务架构和RESTful API主导的时代,HTTP接口在各个业务模块之间扮演着重要的角色。随着业务规模的不断扩大,接口的访问频率和负载也随之增加。为了确保系统的稳定性和性能,接口限速成了一个重要的话题。 1 接口限速的使用场景 接口…...

WSL中为Ubuntu和Debian设置固定IP的终极指南
文章目录 **WSL中为Ubuntu和Debian设置固定IP的终极指南****引言/背景****1. 传统方法****2. 新方法:添加指定IP而不是更改IP****结论**WSL中为Ubuntu和Debian设置固定IP的终极指南 引言/背景 随着WSL(Windows Subsystem for Linux)的普及,越来越多的开发者开始在Windows…...
axios+vite配置反向代理踩坑记录
aixosvite配置反向代理跨域踩坑记录 最近,实习中,一直在写公司的项目。因为公司的项目大多都已经将工程化的东西已经配置好了。导致我昨天自己写项目的时候配置工程化出错!其实,这是一个很简单的问题。之前熟练的时候能够很熟…...

Spring IOC的理解
总: 控制反转(IOC):理论思想,传统java开发模式,对象是由使用者来进行管理,有了spring后,可以交给spring来帮我们进行管理。依赖注入(DI):把对应的…...

2023年京东箱包行业数据分析(京东数据运营)
当前,旅游业全面复苏,这一现象也带动了周边产业的火爆。在全国游客的出行热带动下,箱包产业迎来消费热潮。 根据鲸参谋电商数据分析平台的相关数据显示,2023年7月,京东箱包大盘整体的销量为266万,同比增长…...

对称加密 非对称加密 AC认证 https原理
文章目录 对称加密及漏洞非对称加密及漏洞什么是数据摘要(也称数据指纹)什么是CA认证CA证书签发过程https通信方案 对称加密及漏洞 对称加密是一种加密算法,使用相同的密钥(也称为对称密钥)用于加密和解密数据。在对称…...
如何在PyQt应用程序中使用Qt Designer和Pyuic工具?
如果你想在PyQt应用程序中使用Qt Designer和Pyuic工具,那么首先你需要确保你已经安装了这些工具。你可以通过以下命令在你的Python环境中安装它们: pip install pyqt5 pip install pyqt5-tools安装完成后,你就可以开始使用Qt Designer设计…...

【云计算•云原生】5.云原生之初识DevOps
文章目录 1.DevOps背景2.DevOps概念3.DevOps工具链 1.DevOps背景 软件开发必须包含两个团队:开发团队和运维团队 开发团队负责开发项目,系统迭代更新运维团队负责项目测试以及部署上线,维持系统稳定运行 一个软件周期中是由这两个团队相互…...
20230830工作心得:巧用标记位和For循环遍历
1 巧用标记位和For循环遍历 您可以使用一个 Map<String, List<xxx>> 类型的数据结构来根据手机号分组并保存多条线索。然后,可以按照以下方式进行操作: 1. 设置一个标志位,比如一个布尔变量,用于记录是否已经成功推…...
AUTOSAR规范与ECU软件开发(实践篇)7.9 MCAL模块配置方法及常用接口函数介绍之Can的配置
目录 1、前言 2 、Can模块 (1) Can General配置 (2) CanConfigSet配置 (3) CanMainFunctionRWPeriods配置...

SpringBoot整合websockt实现消息对话
文章目录 前言websockt什么是websockt?websockt和Socket区别代码部分实战应用 前言 websockt 什么是websockt? WebSocket是一种在Web应用程序中实现实时双向通信的技术。Web应用程序通常是基于HTTP协议的,HTTP是一种请求/响应式的协议&…...
MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)MultipartFile 多媒体文件上传
目录 MIME媒体类型介绍MediaTypes 有哪些MultipartFile 类介绍MultipartFile 类 接收的文件是二进制嘛代码举例 上传的文件 实现接口 MultipartFile 类有哪些最终调用接口的方法时,会有哪个类实现 如何决定哪个类去实现呢 Spring 会根据运行环境自动选择合适的实现类…...

数据库(MySQL)的存储过程
一、存储过程介绍 存储过程是事先经过编译并存储在数据库中的一段SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。 存储过程思想上很简单࿰…...

Flutter:getX的学习
前言 学习教程:Getx教程_FlutterGetx系列实战教程 简介 getX是第三方的状态管理插件,不仅具有状态管理的功能,还具有路由管理、主题管理、国际化多语言管理、网络请求、数据验证等功能。相比其他状态管理组件,getX简单、功能强大…...

leetcode - 360周赛
一,2833. 距离原点最远的点 这道题的意思是,遇到 "L" 向左走,遇到 "R" 向右走,遇到 "_" 左右都可以走,那么要想找到距离原点最远的点,就是在找 | "L" "R&qu…...

Android 1.1 背景相关与系统架构分析
目录 1.1 背景相关与系统架构分析 分类 Android 基础入门教程 1.Android背景与当前的状况 2.Android系统特性与平台架构 系统特性: 平台架构图: 架构的简单理解: 3.本节小结: 1.1 背景相关与系统架构分析 分类 Android 基础…...

系统架构技能之设计模式-抽象工厂模式
一、上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式。并且分析了每种模式的应用场景和一些优缺点,我们现在来回顾一下: 简单工厂模式:一个工厂负责所有类型对象的创建,不支持无缝的新增新的类型对象的创建。 工厂模式&…...
clangd的使用,实现跳转提示
一、插件卸载c插件下载clangd 二、设置搜索clangd --compile-commands-dirbuild文件中compile_commands的绝对路径若没有找到compile_commands.json文件可以通过如下方式之后再便于即可生成 cmake项目: 在项目最顶层的.cmake文件中或者CMakeList文件中加入如下命令…...

2023应届生java面试搞笑之一:CAS口误说成开心锁-笑坏面试官
源于:XX网,如果冒犯,表示歉意 面试官:什么是CAS 我:这个简单,开心锁 面试官:WTF? 我:一脸自信,对,就是这个 面试官:哈哈大笑ÿ…...

nginx-concat
为了减少tcp请求数量,nginx从上有服务器获取多个静态资源(css,js)的时候,将多个静态资源合并成一个返回给客户端。 这种前面有两个问号的请求都是用了cancat合并功能。 先到官网下载安装包,拷贝到服务器编译…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...