”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 向您的 Go API 添加 API 速率限制

向您的 Go API 添加 API 速率限制

发布于2024-11-08
浏览:741

Adding API Rate Limiting to Your Go API

好吧,伙计们,到目前为止我们已经介绍了很多内容:JWT 身份验证、数据库连接、日志记录和错误处理。但是,当您的 API 开始受到请求的冲击时会发生什么?如果没有控制,高流量可能会导致响应时间缓慢甚至停机。 ?

本周,我们将通过实施速率限制来控制流量来解决这个问题。我们将使用简单有效的 golang.org/x/time/rate 包。稍后,当我自己的 ThrottleX 解决方案准备就绪时,我将向您展示如何将其集成为更具可扩展性的选项。 (注意,请查看我的 GitHub(github.com/neelp03/throttlex)以获取更新!请随意评论您在其中看到的任何问题 o7)

为什么要进行速率限制? ?

速率限制就像 API 的保镖 — 它控制用户在给定时间范围内可以发出的请求数量。这可以防止您的 API 不堪重负,确保所有用户顺利、公平地访问。速率限制对于以下情况至关重要:

  • 防止滥用:阻止不良行为者或过度热情的用户淹没您的 API。
  • 稳定性:即使在流量高峰期间,也能保持 API 的响应能力和可靠性。
  • 公平性:让资源在用户之间平等共享。

第 1 步:安装时间/费率包

golang.org/x/time/rate 包是扩展 Go 库的一部分,提供了一个简单的基于令牌的速率限制器。首先,您需要安装它:


go get golang.org/x/time/rate


第 2 步:设置速率限制器

让我们创建一个速率限制中间件来控制客户端可以发出的请求数量。在此示例中,我们将客户端限制为每分钟 5 个请求


package main

import (
    "net/http"
    "golang.org/x/time/rate"
    "sync"
    "time"
)

// Create a struct to hold each client's rate limiter
type Client struct {
    limiter *rate.Limiter
}

// In-memory storage for clients
var clients = make(map[string]*Client)
var mu sync.Mutex

// Get a client's rate limiter or create one if it doesn't exist
func getClientLimiter(ip string) *rate.Limiter {
    mu.Lock()
    defer mu.Unlock()

    // If the client already exists, return the existing limiter
    if client, exists := clients[ip]; exists {
        return client.limiter
    }

    // Create a new limiter with 5 requests per minute
    limiter := rate.NewLimiter(5, 1)
    clients[ip] = &Client{limiter: limiter}
    return limiter
}


第 3 步:创建速率限制中间件

现在,让我们在中间件中使用 getClientLimiter 函数,该函数将根据速率限制来限制访问。


func rateLimitingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.RemoteAddr
        limiter := getClientLimiter(ip)

        // Check if the request is allowed
        if !limiter.Allow() {
            http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}


运作原理:

  1. 基于 IP 的限制:每个客户端都通过其 IP 地址进行标识。我们检查客户端的 IP 并为其分配速率限制器。
  2. 请求检查:limiter.Allow()方法检查客户端是否在速率限制内。如果是,则请求将继续到下一个处理程序;如果没有,我们会回复 429 Too Many Requests.

第 4 步:在全球范围内应用中间件 ?

现在让我们将速率限制器连接到 API,以便每个请求都必须通过它:


func main() {
    db = connectDB()
    defer db.Close()

    r := mux.NewRouter()

    // Apply rate-limiting middleware globally
    r.Use(rateLimitingMiddleware)

    // Other middlewares
    r.Use(loggingMiddleware)
    r.Use(errorHandlingMiddleware)

    r.HandleFunc("/login", login).Methods("POST")
    r.Handle("/books", authenticate(http.HandlerFunc(getBooks))).Methods("GET")
    r.Handle("/books", authenticate(http.HandlerFunc(createBook))).Methods("POST")

    fmt.Println("Server started on port :8000")
    log.Fatal(http.ListenAndServe(":8000", r))
}


通过应用 r.Use(rateLimitingMiddleware),我们确保每个传入请求在到达任何端点之前都会受到速率限制器的检查。


第 5 步:测试速率限制?

启动您的服务器:


go run main.go


现在,让我们使用一些请求来访问 API。可以使用带有curl的循环来模拟连续多个请求:


for i in {1..10}; do curl http://localhost:8000/books; done


由于我们将限制设置为每分钟 5 个请求,一旦超出允许的速率,您应该会看到 429 Too Many Requests 响应。


接下来是什么?

现在您已经有了它——使用 golang.org/x/time/rate 进行速率限制,以保持您的 API 在压力下保持稳定和响应。速率限制对于任何可扩展 API 来说都是一个至关重要的工具,我们在这里只是触及了表面。

一旦 ThrottleX 准备就绪,我将发布后续教程,向您展示如何将其集成到 Go API 中,以获得更大的灵活性和分布式速率限制。请关注我的 ThrottleX GitHub 存储库以获取更新!

下周,我们将使用 Docker 容器化我们的 API,以便它可以在任何地方运行。请继续关注,祝您编码愉快! ??

版本声明 本文转载于:https://dev.to/neelp03/adding-api-rate-limiting-to-your-go-api-3fo8?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • Java开发者如何保护数据库凭证免受反编译?
    Java开发者如何保护数据库凭证免受反编译?
    在java 在单独的配置文件保护数据库凭证的最有效方法中存储凭据是将它们存储在单独的配置文件中。该文件可以在运行时加载,从而使登录数据从编译的二进制文件中远离。使用prevereness class import java.util.prefs.preferences; 公共类示例{ 首选项...
    编程 发布于2025-05-09
  • 如何有效地选择熊猫数据框中的列?
    如何有效地选择熊猫数据框中的列?
    在处理数据操作任务时,在Pandas DataFrames 中选择列时,选择特定列的必要条件是必要的。在Pandas中,选择列的各种选项。选项1:使用列名 如果已知列索引,请使用ILOC函数选择它们。请注意,python索引基于零。 df1 = df.iloc [:,0:2]#使用索引0和1 c...
    编程 发布于2025-05-09
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-05-09
  • 哪种在JavaScript中声明多个变量的方法更可维护?
    哪种在JavaScript中声明多个变量的方法更可维护?
    在JavaScript中声明多个变量:探索两个方法在JavaScript中,开发人员经常遇到需要声明多个变量的需要。对此的两种常见方法是:在单独的行上声明每个变量: 当涉及性能时,这两种方法本质上都是等效的。但是,可维护性可能会有所不同。 第一个方法被认为更易于维护。每个声明都是其自己的语句,使其...
    编程 发布于2025-05-09
  • Go语言如何动态发现导出包类型?
    Go语言如何动态发现导出包类型?
    与反射软件包中的有限类型的发现能力相反,本文探索了替代方法,探索了在Runruntime。go import( “ FMT” “去/进口商” ) func main(){ pkg,err:= incorter.default()。导入(“ time”) 如果err...
    编程 发布于2025-05-09
  • 如何有效地转换PHP中的时区?
    如何有效地转换PHP中的时区?
    在PHP 利用dateTime对象和functions DateTime对象及其相应的功能别名为时区转换提供方便的方法。例如: //定义用户的时区 date_default_timezone_set('欧洲/伦敦'); //创建DateTime对象 $ dateTime = ne...
    编程 发布于2025-05-09
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-05-09
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-05-09
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月份)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将...
    编程 发布于2025-05-09
  • Python元类工作原理及类创建与定制
    Python元类工作原理及类创建与定制
    python中的metaclasses是什么? Metaclasses负责在Python中创建类对象。就像类创建实例一样,元类也创建类。他们提供了对类创建过程的控制层,允许自定义类行为和属性。在Python中理解类作为对象的概念,类是描述用于创建新实例或对象的蓝图的对象。这意味着类本身是使用类关...
    编程 发布于2025-05-09
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-05-09
  • 如何检查对象是否具有Python中的特定属性?
    如何检查对象是否具有Python中的特定属性?
    方法来确定对象属性存在寻求一种方法来验证对象中特定属性的存在。考虑以下示例,其中尝试访问不确定属性会引起错误: >>> a = someClass() >>> A.property Trackback(最近的最新电话): 文件“ ”,第1行, AttributeError: SomeClass...
    编程 发布于2025-05-09
  • 您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    在javascript console 中显示颜色是可以使用chrome的控制台显示彩色文本,例如红色的redors,for for for for错误消息?回答是的,可以使用CSS将颜色添加到Chrome和Firefox中的控制台显示的消息(版本31或更高版本)中。要实现这一目标,请使用以下模...
    编程 发布于2025-05-09
  • 在JavaScript中如何获取实际渲染的字体,当CSS字体属性未定义时?
    在JavaScript中如何获取实际渲染的字体,当CSS字体属性未定义时?
    Accessing Actual Rendered Font when Undefined in CSSWhen accessing the font properties of an element, the JavaScript object.style.fontFamily and objec...
    编程 发布于2025-05-09
  • 如何使用node-mysql在单个查询中执行多个SQL语句?
    如何使用node-mysql在单个查询中执行多个SQL语句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    编程 发布于2025-05-09

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3