当前位置: 首页 > news >正文

基于Gin框架的HTTP接口限速实践

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

1 接口限速的使用场景

接口限速的使用场景主要涉及以下几种情况:

  1. 防止API滥用:在某些情况下,如果没有有效的限速机制,恶意用户可能会无限制地调用API,导致系统过载。通过接口限速,我们可以限制每个用户对特定接口的访问频率,从而防止API滥用。
  2. 保护服务稳定性:在某些情况下,某些高频调用可能会给后端服务带来巨大的压力,影响服务的稳定性和性能。通过接口限速,我们可以限制对这些接口的访问频率,从而保护服务的稳定性。
  3. 资源合理分配:在一些情况下,我们需要对系统资源进行合理的分配,确保每个用户都能得到公平的资源使用。通过接口限速,我们可以根据用户的请求频率进行资源分配,从而保证公平性。

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、提高用户体验等。

http://www.lryc.cn/news/151176.html

相关文章:

  • WSL中为Ubuntu和Debian设置固定IP的终极指南
  • axios+vite配置反向代理踩坑记录
  • Spring IOC的理解
  • 2023年京东箱包行业数据分析(京东数据运营)
  • 对称加密 非对称加密 AC认证 https原理
  • 如何在PyQt应用程序中使用Qt Designer和Pyuic工具?
  • 【云计算•云原生】5.云原生之初识DevOps
  • 20230830工作心得:巧用标记位和For循环遍历
  • AUTOSAR规范与ECU软件开发(实践篇)7.9 MCAL模块配置方法及常用接口函数介绍之Can的配置
  • SpringBoot整合websockt实现消息对话
  • MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)MultipartFile 多媒体文件上传
  • 数据库(MySQL)的存储过程
  • Flutter:getX的学习
  • leetcode - 360周赛
  • Android 1.1 背景相关与系统架构分析
  • 系统架构技能之设计模式-抽象工厂模式
  • clangd的使用,实现跳转提示
  • 2023应届生java面试搞笑之一:CAS口误说成开心锁-笑坏面试官
  • nginx-concat
  • Java 大厂面试 —— 常见集合篇 List HashMap 红黑树
  • 剪枝基础与实战(5): 剪枝代码详解
  • Acwing 897. 最长公共子序列 (每日一题)
  • CSS中border-radius的来美化table的实战方案
  • 移除链表元素_每日一题
  • spring boot + Consul 示例 (Kotlin版)
  • Git企业开发控制理论和实操-从入门到深入(四)|Git的远程操作|Gitee
  • SpringCloudAlibaba Gateway(二)详解-内置Predicate、Filter及自定义Predicate、Filter
  • 调用chat-gpt
  • Element组件浅尝辄止6:Dialog 对话框组件
  • Bert和LSTM:情绪分类中的表现