在这个图书馆项目中,我们采用令牌桶限流算法,具体原理请参看《分布式高可用-流量控制-1 流控策略》文章。
完整代码:
https://github.com/Justin02180218/micro-kit
在 pkg 下新建目录 ratelimits,创建 ratelimit.go 文件:
在 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)),
}
下一篇文章,我们给微服务加入服务注册与发现功能。
完整代码:
https://github.com/Justin02180218/micro-kit
更多【分布式专辑】【架构实战专辑】系列文章,请关注公众号