Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go语言速率限流

Go语言中的速率限流策略全面详解

作者:低配全栈

这篇文章主要为大家介绍了Go语言中的速率限流策略全面详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

前一篇文章中我们提到,为了防止缓存穿透,我们可以在应用里面的缓存层的上一层添加了singleflight。但是,我们也提到,即使使用了singleflight,我们一样还是会存在问题:

使用singleflight本身并不会直接导致OOM的发生,但是需要考虑到极端情况下导致内存使用增加,如果有大量唯一的请求快速连续到来,并且它们的处理时间相对较长,则这些请求可能会在内存中积累,从而增加内存使用.

什么,OpenAI又“雪崩”了?

为了解决这种问题,今天在这里介绍一下GO语言中限流策略(Rating Limit)的使用。

1. 什么是速率限流

在 Go 语言中,Rate Limit(速率限制)是一种控制资源利用率的重要机制,尤其适用于控制对外部资源的访问速率,例如 API 请求或数据库操作。Go 标准库中的golang.org/x/time/rate包提供了实现速率限制的功能。

核心概念

2. 基本使用

首先看一个具体的例子:

import (
  "context"
  "fmt"
  "log"
  "time"
  "golang.org/x/time/rate"
)
func main() {
  // 创建一个新的限制器,每秒产生5个令牌,最大桶容量为5
  limiter := rate.NewLimiter(5, 5)
  // 模拟连续请求
  for i := 0; i < 10; i++ {
    i := i
    go func() {
      // 等待下一个令牌
      err := limiter.Wait(context.Background())
      if err != nil {
        log.Fatal(err)
      }
      // 令牌已获取,执行API请求
      fmt.Println("Sending API request", i, "at", time.Now().Format(time.RFC3339))
      // 这里可以添加执行实际 API 请求的代码
    }()
  }
  time.Sleep(10 * time.Second)
}

运行结果如下:

我们可以看到,因为rate.Limit的限制,大约每1秒被限制发送5次请求。

细节说明

3. 动态调整限速器速率

在 Go 语言中,rate.Limiter 提供了动态调整速率的功能。通过这种方式i允许你在运行时根据需要改变速率限制,这在很多实际应用中非常有用,比如基于当前服务器负载或外部服务的可用性来调整请求速率。

rate.Limiter 提供了 SetLimit 和 SetBurst 两个方法来动态调整限制器的速率和桶大小:

package main
import (
  "context"
  "fmt"
  "time"
  "golang.org/x/time/rate"
)
func main() {
  // 初始速率为每秒2个请求
  limiter := rate.NewLimiter(2, 2)
  // 模拟动态调整速率
  go func() {
    for {
      time.Sleep(5 * time.Second)
      // 每5秒动态调整速率和桶大小
      newRate := rate.Limit(float64(time.Now().Second()) / 10)
      limiter.SetLimit(newRate)
      limiter.SetBurst(int(newRate))
      fmt.Println("Rate updated to:", newRate)
    }
  }()
  // 模拟请求
  for i := 0; ; i++ {
    err := limiter.Wait(context.Background())
    if err != nil {
      fmt.Println("Error:", err)
      continue
    }
    fmt.Println("Request", i, "at", time.Now().Format(time.RFC3339))
  }
}

通过动态调整 rate.Limiter 的速率和桶大小,你可以灵活地控制应用中的速率限制,使其更加适应变化的环境和需求。上述例子中,每5s会更新速率,每次更新速率之后,请求数量可以实现动态调整:

运行结果:

4. 应用场景

rate.Limiter 在 Go 语言中的应用场景广泛,主要用于控制资源的使用频率,以防止过载、滥用或达到限制。以下是一些常见的应用场景:

1. API 请求限制

当与外部服务(如 REST API)交互时,通常会有每秒或每分钟的请求限制。使用 rate.Limiter 可以确保你的应用不会超过这些限制,从而避免触发服务端的速率限制错误或被暂时禁止访问。

2. 数据库访问控制

在高并发环境下,过多的数据库查询可能会导致性能下降或服务不可用。通过限制数据库操作的频率,可以减轻数据库的负载,提高应用的稳定性和响应速度。

3. 限制用户操作

在某些应用中,可能需要限制用户执行特定操作的频率,例如发送消息、提交表单或请求验证码。这有助于防止滥用和自动化攻击,同时保持系统资源的合理使用。

总结

rate.Limiter 的使用场景体现了其灵活性和实用性。无论是保护外部服务不被过载、控制资源访问、还是提高应用的整体稳定性,它都是一个非常有效的工具。在设计系统时,考虑到这些场景,合理地应用速率限制,可以显著提升系统的健壮性和用户体验。

以上就是Go语言中的速率限流策略全面详解的详细内容,更多关于Go语言速率限流的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文