六,令牌桶限流

令牌桶限流

在这个图书馆项目中,我们采用令牌桶限流算法,具体原理请参看《分布式高可用-流量控制-1 流控策略》文章。

项目中应用

完整代码:

https://github.com/Justin02180218/micro-kit

在 pkg 下新建目录 ratelimits,创建 ratelimit.go 文件:

六,令牌桶限流_第1张图片

 

 

在 go kit 的 endpoint 层进行限流,采用装饰器模式 

var ErrLimitExceed = errors.New(" Rate Limit Exceed ")

func NewTokenBucketLimiter(tb *ratelimit.Bucket) endpoint.Middleware {
    return func(next endpoint.Endpoint) endpoint.Endpoint {
        return func(ctx context.Context, request interface{}) (response interface{}, err error) {
            // 从令牌桶中取令牌,如果没有令牌则返回提示信息。
            if tb.TakeAvailable(1) == 0 {
                return nil, ErrLimitExceed
            }
            return next(ctx, request)
        }
    }
}

配置文件

ratelimit:
  fillInterval: 1
  capacity: 3
type RatelimitConfig struct {
    FillInterval int `json:"fillInterval" yaml:"fillInterval"`
    Capacity     int `json:"capacity" yaml:"capacity"`
}

为了测试方便,配置令牌桶的容量为3个,填充间隔为1秒。当并发请求超过3个,就会触发限流,提示错误信息。

修改 main.go

以 library-user-service 为例,其他微服务也是相同的写法

// 创建令牌桶
bucket := ratelimit.NewBucket(time.Second*time.Duration(configs.Conf.RatelimitConfig.FillInterval), int64(configs.Conf.RatelimitConfig.Capacity))
ratelimit := ratelimits.NewTokenBucketLimiter(bucket)

userEndpoints := &endpoint.UserEndpoints{
    RegisterEndpoint:          ratelimit(endpoint.MakeRegisterEndpoint(userService)),
    FindByIDEndpoint:          ratelimit(endpoint.MakeFindByIDEndpoint(userService)),
    FindByEmailEndpoint:       ratelimit(endpoint.MakeFindByEmailEndpoint(userService)),
    FindBooksByUserIDEndpoint: ratelimit(endpoint.MakeFindBooksByUserIDEndpoint(userService)),
}

测试 

六,令牌桶限流_第2张图片

下一篇文章,我们给微服务加入服务注册与发现功能。

完整代码:

https://github.com/Justin02180218/micro-kit


更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号

你可能感兴趣的:(docker,微服务,go,go语言,微服务架构,docker,k8s)