func StreamServerInterceptor(limiter Limiter) grpc.StreamServerInterceptor
func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor

type Limiter

限制器定义了执行请求速率限制的接口。如果Limit函数返回true,请求将被拒绝。否则,请求将通过。

  1. type Limiter interface {
  2. Limit() bool
  3. }

type Bucket

github.com/juju/ratelimit

  1. type Bucket struct {
  2. // contains filtered or unexported fields
  3. }

func NewBucket(fillInterval time.Duration, capacity int64) *Bucket

  • 按指定间隔向桶里填充一个令牌,直到 capacity,桶初始化是满的

func (tb Bucket) Available() int64:返回令牌桶可用的数量
func (tb
Bucket) Capacity() int64:返回桶初始容量
func (tb Bucket) Rate() float64:填充速率,以秒为单位
func (tb
Bucket) TakeAvailable(count int64) int64 不阻塞取出,没有返回0
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)

  • TakeMaxDuration类似于Take,只是它只在令牌的等待时间不大于maxWait时才从bucket中获取令牌。
  • 如果等待令牌可用的时间比maxWait长,那么它将不执行任何操作,并报告false,否则它将返回调用者应该等待的时间,直到令牌真正可用,然后报告true。

func (tb Bucket) Wait(count int64) 阻塞取出,桶内没有可用的则等待
func (tb
Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool

  • 阻塞取出,桶内没有可用的则等待maxWait,到maxWait还没可用,则返回false

    例子:

    ```go package main

import ( “context” “errors” “fmt” “github.com/grpc-ecosystem/go-grpc-middleware” “github.com/grpc-ecosystem/go-grpc-middleware/ratelimit” juju “github.com/juju/ratelimit” “google.golang.org/grpc” “log” “net” pb “study/grpc/protobuf/person” “time” )

const ( port = “:8080” )

type Limiter struct{ Bucket *juju.Bucket }

func (this *Limiter) Limit() bool { token := this.Bucket.TakeAvailable(1) fmt.Println(“桶可用数量:”,this.Bucket.Available()) if token == 0 { return true } return false }

func main() { lis, err := net.Listen(“tcp”, port) if err != nil { log.Fatalf(“failed to listen: %v”, err) } limiter := &Limiter{juju.NewBucket(time.Second*2,2)} opts := grpc_middleware.WithUnaryServerChain(ratelimit.UnaryServerInterceptor(limiter)) s := grpc.NewServer(opts) //起一个服务 pb.RegisterPersonserverServer(s,&Server{})

  1. if err := s.Serve(lis); err != nil {
  2. log.Fatalf("failed to serve: %v", err)
  3. }

}

超速client端的错误: rpc error: code = ResourceExhausted desc = /person.personserver/GetPerson is rejected by grpc_ratelimit middleware, please retry later. refused it. ```