Limiter

The limit.PeriodLimit is mainly used to limit requests within a period. It is implemented based on Redis and performs rate limiting operations through Lua scripts.

Constants

  1. const (
  2. // Unknown means not initialized state.
  3. Unknown = iota
  4. // Allowed means allowed state.
  5. Allowed
  6. // HitQuota means this request exactly hit the quota.
  7. HitQuota
  8. // OverQuota means passed the quota.
  9. OverQuota
  10. )

Variables

  1. var (
  2. // ErrUnknownCode is an error that represents unknown status code.
  3. ErrUnknownCode = errors.New("unknown status code")
  4. )

Types

PeriodLimit

PeriodLimit is used to limit requests during a specific period. It has the following fields:

PeriodOption

PeriodOption defines the method to customize a PeriodLimit.

Functions

NewPeriodLimit

Creates a new PeriodLimit instance.

  1. func NewPeriodLimit(period, quota int, limitStore *redis.Redis, keyPrefix string, opts ...PeriodOption) *PeriodLimit

Parameters

  • period: The time period in seconds for which the rate limit applies.
  • quota: The maximum number of allowed requests within the specified period.
  • limitStore: The Redis store instance used for keeping track of the limits.
  • keyPrefix: A prefix for the keys used in Redis to distinguish different limits.
  • opts: Optional customization options for the PeriodLimit instance.

Example

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/zeromicro/go-zero/core/stores/redis"
  5. "limit"
  6. )
  7. func main() {
  8. store := redis.New("localhost:6379")
  9. limiter := limit.NewPeriodLimit(60, 10, store, "exampleKey")
  10. result, err := limiter.Take("user1")
  11. if err != nil {
  12. fmt.Println("Error:", err)
  13. return
  14. }
  15. switch result {
  16. case limit.Allowed:
  17. fmt.Println("Request allowed")
  18. case limit.HitQuota:
  19. fmt.Println("Hit the quota")
  20. case limit.OverQuota:
  21. fmt.Println("Over the quota")
  22. default:
  23. fmt.Println("Unknown status")
  24. }
  25. }

Take

Requests a permit, returns the permit state.

  1. func (h *PeriodLimit) Take(key string) (int, error)

Parameters

  • key: The key to identify the requester. This is usually a unique identifier for the client or user making the request.

Returns

  • An integer representing the permit state (Allowed, HitQuota, OverQuota, or Unknown).
  • An error if something goes wrong during the request processing.

TakeCtx

Requests a permit with context, returns the permit state.

  1. func (h *PeriodLimit) TakeCtx(ctx context.Context, key string) (int, error)

Parameters

  • ctx: The context to control the execution of this function, useful for timeouts and cancellations.
  • key: The key to identify the requester. This is usually a unique identifier for the client or user making the request.

Returns

  • An integer representing the permit state (Allowed, HitQuota, OverQuota, or Unknown).
  • An error if something goes wrong during the request processing.

Align

Returns a PeriodOption to align the time period.

  1. func Align() PeriodOption

Returns

  • A PeriodOption that can be used to configure a PeriodLimit to align its time periods. For example, aligning to the start of a day.

Example

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/zeromicro/go-zero/core/stores/redis"
  5. "limit"
  6. )
  7. func main() {
  8. store := redis.New("localhost:6379")
  9. limiter := limit.NewPeriodLimit(86400, 5, store, "sms_limit", limit.Align())
  10. result, err := limiter.Take("user1")
  11. if err != nil {
  12. fmt.Println("Error:", err)
  13. return
  14. }
  15. switch result {
  16. case limit.Allowed:
  17. fmt.Println("SMS request allowed")
  18. case limit.HitQuota:
  19. fmt.Println("Hit the daily quota")
  20. case limit.OverQuota:
  21. fmt.Println("Over the daily quota")
  22. default:
  23. fmt.Println("Unknown status")
  24. }
  25. }