limit.TokenLimiter

TokenLimiter 是一个用来控制事件在一秒钟内发生频率的限流器。它依赖于 Redis 来存储令牌桶的状态,并且提供了备用的限流机制,以防 Redis 不可用。

新建 TokenLimiter

  1. func NewTokenLimiter(rate, burst int, store *redis.Redis, key string) *TokenLimiter

创建并返回一个新的 TokenLimiter 实例。

  • 参数:

    • rate: 每秒允许的事件数。
    • burst: 允许的突发事件数。
    • store: Redis 客户端实例。
    • key: 用于生成 Redis 存储键的关键字。
  • 返回值: 一个 TokenLimiter 实例。

Allow

  1. func (lim *TokenLimiter) Allow() bool

检查是否允许一个事件发生,这是 AllowN(time.Now(), 1) 的简写。

  • 返回值: 如果允许事件发生,返回 true;否则返回 false

AllowCtx

  1. func (lim *TokenLimiter) AllowCtx(ctx context.Context) bool

带有上下文信息的 Allow 方法,是 AllowNCtx(ctx, time.Now(), 1) 的简写。

  • 参数:

    • ctx: 上下文信息,用于控制请求的生命周期。
  • 返回值: 如果允许事件发生,返回 true;否则返回 false

AllowN

  1. func (lim *TokenLimiter) AllowN(now time.Time, n int) bool

检查在指定时间点是否允许 n 个事件发生。

  • 参数:

    • now: 当前时间。
    • n: 请求的事件数。
  • 返回值: 如果允许事件发生,返回 true;否则返回 false

AllowNCtx

  1. func (lim *TokenLimiter) AllowNCtx(ctx context.Context, now time.Time, n int) bool

带有上下文信息的 AllowN 方法,检查在指定时间点是否允许 n 个事件发生。

  • 参数:

    • ctx: 上下文信息,用于控制请求的生命周期。
    • now: 当前时间。
    • n: 请求的事件数。
  • 返回值: 如果允许事件发生,返回 true;否则返回 false

示例

以下是一些如何使用 TokenLimiter 的示例:

简单示例

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/zeromicro/go-zero/core/limit"
  6. "github.com/zeromicro/go-zero/core/stores/redis"
  7. )
  8. func main() {
  9. store := redis.NewRedis("localhost:6379", redis.NodeType)
  10. limiter := limit.NewTokenLimiter(10, 20, store, "example-key")
  11. if limiter.Allow() {
  12. fmt.Println("Request allowed")
  13. } else {
  14. fmt.Println("Request not allowed")
  15. }
  16. }

在这个示例中,我们创建了一个每秒最多允许 10 个事件、最多允许 20 个突发事件的 TokenLimiter。然后我们使用 Allow 方法检查是否允许当前请求。

使用上下文信息的示例

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/zeromicro/go-zero/core/limit"
  7. "github.com/zeromicro/go-zero/core/stores/redis"
  8. )
  9. func main() {
  10. ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
  11. defer cancel()
  12. store := redis.NewRedis("localhost:6379", redis.NodeType)
  13. limiter := limit.NewTokenLimiter(5, 10, store, "example-key")
  14. if limiter.AllowCtx(ctx) {
  15. fmt.Println("Request allowed with context")
  16. } else {
  17. fmt.Println("Request not allowed with context")
  18. }
  19. }

在这个示例中,我们使用上下文信息来控制请求的生命周期。如果在指定的时间内未能获得许可,AllowCtx 方法将返回 false

检查多个事件的示例

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/zeromicro/go-zero/core/limit"
  6. "github.com/zeromicro/go-zero/core/stores/redis"
  7. )
  8. func main() {
  9. store := redis.NewRedis("localhost:6379", redis.NodeType)
  10. limiter := limit.NewTokenLimiter(10, 20, store, "example-key")
  11. now := time.Now()
  12. requests := 3
  13. if limiter.AllowN(now, requests) {
  14. fmt.Printf("%d requests allowed at %v\n", requests, now)
  15. } else {
  16. fmt.Printf("%d requests not allowed at %v\n", requests, now)
  17. }
  18. }

在这个示例中,我们检查在当前时间点是否允许 3 个事件发生。如果允许,将输出相应的信息。