搜索
首页后端开发Golang使用 Redis 对 Golang API 进行速率限制

用更简单的话来说,速率限制,它是一种限制用户或客户端在给定时间范围内可以向 API 发出请求数量的技术。过去,当您尝试访问天气或笑话 API 时,您可能遇到过收到“超出速率限制”消息的情况。关于为什么要限制 API 的速率有很多争论,但一些重要的争论是合理使用它、确保其安全、保护资源免于过载等。

在本博客中,我们将使用 Gin 框架使用 Golang 创建一个 HTTP 服务器,使用 Redis 对端点应用速率限制功能,并存储某个时间范围内 IP 向服务器发出的请求总数。如果超过我们设置的限制,我们会给出错误消息。

如果你不知道 Gin 和 Redis 是什么。 Gin 是一个用 Golang 编写的 Web 框架。它有助于创建一个简单而快速的服务器,而无需编写大量代码。 Redis 它是一个内存中的键值数据存储,可以用作数据库或缓存功能。

先决条件

  • 熟悉 Golang、Gin 和 Redis
  • 一个 Redis 实例(我们可以使用 Docker 或远程机器)

现在,让我们开始吧。

要初始化项目,请运行 go mod init ;例如,go mod init github.com/Pradumnasaraf/go-redis。

然后让我们使用 Gin 框架创建一个简单的 HTTP 服务器,然后应用对其进行速率限制的逻辑。您可以复制下面的代码。这是非常基本的。当我们点击 /message 端点时,服务器将回复一条消息。

复制以下代码后,运行 go mod tidy 即可自动安装我们导入的软件包。

package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/message", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "You can make more requests",
        })
    })
    r.Run(":8081") //listen and serve on localhost:8081
} 

我们可以通过在终端中执行 go run main.go 来运行服务器,并在终端中看到此消息。

Rate Limiting a Golang API using Redis

要测试它,我们可以访问 localhost:8081/message 我们将在浏览器中看到此消息。

Rate Limiting a Golang API using Redis

现在我们的服务器正在运行,让我们为 /message 路由设置速率限制功能。我们将使用 go-redis/redis_rate 包。感谢这个包的创建者,我们不需要从头开始编写处理和检查限制的逻辑。它将为我们完成所有繁重的工作。

下面是实现限速功能后的完整代码。我们会理解其中的每一点。只是尽早给出完整的代码,以避免任何混淆并了解不同部分如何协同工作。

复制代码后,运行 go mod tidy 来安装所有导入的软件包。现在让我们跳转并理解代码(在代码片段下方)。

package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/message", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "You can make more requests",
        })
    })
    r.Run(":8081") //listen and serve on localhost:8081
} 

我们先直接跳到rateLimiter()函数来理解一下。该函数需要一个参数,即请求的 IP 地址,我们可以通过主函数中的 c.ClientIP() 获取该地址。如果达到限制,我们将返回一个错误,否则将其保持为零。大部分代码是我们从官方 GitHub 存储库中获取的样板代码。这里需要仔细研究的关键功能是 limiter.Allow() 函数。 Addr:获取 Redis 实例的 URL 路径值。我正在使用 Docker 在本地运行它。您可以使用任何内容,只需确保相应地替换 URL 即可。

package main

import (
    "context"
    "errors"
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/go-redis/redis_rate/v10"
    "github.com/redis/go-redis/v9"
)

func main() {
    r := gin.Default()
    r.GET("/message", func(c *gin.Context) {
        err := rateLimiter(c.ClientIP())
        if err != nil {
            c.JSON(http.StatusTooManyRequests, gin.H{
                "message": "you have hit the limit",
            })
            return
        }
        c.JSON(http.StatusOK, gin.H{
            "message": "You can make more requests",
        })
    })
    r.Run(":8081")
}

func rateLimiter(clientIP string) error {
    ctx := context.Background()
    rdb := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })

    limiter := redis_rate.NewLimiter(rdb)
    res, err := limiter.Allow(ctx, clientIP, redis_rate.PerMinute(10))
    if err != nil {
        panic(err)
    }
    if res.Remaining == 0 {
        return errors.New("Rate")
    }

    return nil
}

它有三个参数,第一个是 ctx,第二个是 Key,Redis 数据库的 Key(值的键),第三个是限制。因此,该函数将 clientIP 地址存储为键,将默认限制存储为值,并在发出请求时减少它。这种结构的原因是Redis数据库需要唯一标识和唯一键来存储键值对类型的数据,并且每个IP地址都以自己的方式唯一,这就是为什么我们使用IP地址而不是用户名,第三个参数 redis_rate.PerMinute(10) 可以根据我们的需要进行修改,我们可以设置限制 PerSecond, PerHour,等等,并设置括号内的值,表示每分钟/秒/小时可以发出多少个请求。在我们的例子中,它是每分钟 10 个。是的,设置就这么简单。

最后,我们通过 res.Remaining 检查是否有剩余配额。如果它为零,我们将返回一个错误消息,否则我们将返回 nil。例如,您还可以执行 res.Limit.Rate 来检查限制率等。您可以尝试并深入研究它。

现在是 main() 函数:

res, err := limiter.Allow(ctx, clientIP, redis_rate.PerMinute(10))

一切都几乎一样。在 /message 路由中,现在每次路由命中时,我们都会调用rateLimit()函数并向其传递一个 ClientIP 地址,并将返回值(错误)值存储在 err 变量中。如果出现错误,我们将返回 429,即 http.StatusTooManyRequests,以及一条消息“message”:“您已达到限制”。如果该人有剩余限制并且rateLimit()没有返回错误,它将正常工作,就像之前所做的那样并服务于请求。

这就是所有的解释。现在让我们测试一下工作情况。通过执行相同的命令重新运行服务器。我们将第一次看到之前收到的相同消息。现在刷新您的浏览器 10 次(因为我们设置了每分钟 10 次的限制),您将在浏览器中看到错误消息。

Rate Limiting a Golang API using Redis

我们还可以通过查看终端中的日志来验证这一点。 Gin 提供了很好的开箱即用的登录功能。一分钟后它将恢复我们的限制配额。

Rate Limiting a Golang API using Redis

本博客到此结束,我希望您喜欢阅读,就像我喜欢写这篇文章一样。我很高兴您能坚持到最后,非常感谢您的支持。我还经常在 X (Twitter) 上谈论 Golang 以及其他内容,例如开源和 Docker。你可以在那里联系我。

以上是使用 Redis 对 Golang API 进行速率限制的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
GO中的字符串操纵:掌握'字符串”软件包GO中的字符串操纵:掌握'字符串”软件包May 14, 2025 am 12:19 AM

掌握Go语言中的strings包可以提高文本处理能力和开发效率。1)使用Contains函数检查子字符串,2)用Index函数查找子字符串位置,3)Join函数高效拼接字符串切片,4)Replace函数替换子字符串。注意避免常见错误,如未检查空字符串和大字符串操作性能问题。

去'字符串”包装提示和技巧去'字符串”包装提示和技巧May 14, 2025 am 12:18 AM

你应该关心Go语言中的strings包,因为它能简化字符串操作,使代码更清晰高效。1)使用strings.Join高效拼接字符串;2)用strings.Fields按空白符分割字符串;3)通过strings.Index和strings.LastIndex查找子串位置;4)用strings.ReplaceAll进行字符串替换;5)利用strings.Builder进行高效字符串拼接;6)始终验证输入以避免意外结果。

GO中的'字符串”软件包:您的首选字符串操作GO中的'字符串”软件包:您的首选字符串操作May 14, 2025 am 12:17 AM

thestringspackageingoisesential forefficientstringManipulation.1)itoffersSimpleyetpoperfulfunctionsFortaskSlikeCheckingSslingSubstringsStringStringsStringsandStringsN.2)ithandhishiCodeDewell,withFunctionsLikestrings.fieldsfieldsfieldsfordsforeflikester.fieldsfordsforwhitespace-fieldsforwhitespace-separatedvalues.3)3)

Go Bytes软件包与字符串软件包:我应该使用哪个?Go Bytes软件包与字符串软件包:我应该使用哪个?May 14, 2025 am 12:12 AM

WhendecidingbetweenGo'sbytespackageandstringspackage,usebytes.Bufferforbinarydataandstrings.Builderforstringoperations.1)Usebytes.Bufferforworkingwithbyteslices,binarydata,appendingdifferentdatatypes,andwritingtoio.Writer.2)Usestrings.Builderforstrin

如何使用'字符串”软件包逐步操纵字符串如何使用'字符串”软件包逐步操纵字符串May 13, 2025 am 12:12 AM

Go的strings包提供了多种字符串操作功能。1)使用strings.Contains检查子字符串。2)用strings.Split将字符串分割成子字符串切片。3)通过strings.Join合并字符串。4)用strings.TrimSpace或strings.Trim去除字符串首尾的空白或指定字符。5)用strings.ReplaceAll替换所有指定子字符串。6)使用strings.HasPrefix或strings.HasSuffix检查字符串的前缀或后缀。

Go Strings软件包:如何改进我的代码?Go Strings软件包:如何改进我的代码?May 13, 2025 am 12:10 AM

使用Go语言的strings包可以提升代码质量。1)使用strings.Join()优雅地连接字符串数组,避免性能开销。2)结合strings.Split()和strings.Contains()处理文本,注意大小写敏感问题。3)避免滥用strings.Replace(),考虑使用正则表达式进行大量替换。4)使用strings.Builder提高频繁拼接字符串的性能。

GO BYTES软件包中最有用的功能是什么?GO BYTES软件包中最有用的功能是什么?May 13, 2025 am 12:09 AM

Go的bytes包提供了多种实用的函数来处理字节切片。1.bytes.Contains用于检查字节切片是否包含特定序列。2.bytes.Split用于将字节切片分割成smallerpieces。3.bytes.Join用于将多个字节切片连接成一个。4.bytes.TrimSpace用于去除字节切片的前后空白。5.bytes.Equal用于比较两个字节切片是否相等。6.bytes.Index用于查找子切片在largerslice中的起始索引。

使用GO的'编码/二进制”软件包掌握二进制数据处理:综合指南使用GO的'编码/二进制”软件包掌握二进制数据处理:综合指南May 13, 2025 am 12:07 AM

theEncoding/binarypackageingoisesenebecapeitProvidesAstandArdArdArdArdArdArdArdArdAndWriteBinaryData,确保Cross-cross-platformCompatibilitiational and handhandlingdifferentendenness.itoffersfunctionslikeread,写下,写,dearte,readuvarint,andwriteuvarint,andWriteuvarIntforPreciseControloverBinary

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器