首页  >  文章  >  后端开发  >  向您的 Go API 添加 API 速率限制

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

Linda Hamilton
Linda Hamilton原创
2024-10-07 10:49:30254浏览

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 太多请求 响应。


接下来是什么?

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

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

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

以上是向您的 Go API 添加 API 速率限制的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn