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

2024-02-22 08:40

本文主要是介绍基于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、提高用户体验等。

这篇关于基于Gin框架的HTTP接口限速实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/734711

相关文章

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

Python 中的 with open文件操作的最佳实践

《Python中的withopen文件操作的最佳实践》在Python中,withopen()提供了一个简洁而安全的方式来处理文件操作,它不仅能确保文件在操作完成后自动关闭,还能处理文件操作中的异... 目录什么是 with open()?为什么使用 with open()?使用 with open() 进行

Nginx中配置HTTP/2协议的详细指南

《Nginx中配置HTTP/2协议的详细指南》HTTP/2是HTTP协议的下一代版本,旨在提高性能、减少延迟并优化现代网络环境中的通信效率,本文将为大家介绍Nginx配置HTTP/2协议想详细步骤,需... 目录一、HTTP/2 协议概述1.HTTP/22. HTTP/2 的核心特性3. HTTP/2 的优

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio