四、 go-kit 微服务的限流实现

本贴最后更新于 2180 天前,其中的信息可能已经水流花落

介绍

go-kit 提供了限流模块,该模块采用令牌桶算法实现,其实是封装了一下 golang 自带的 golang.org/x/time/rate 包来实现的。

令牌桶

令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;而如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。

令牌桶算法的基本过程如下:

假如用户配置的平均发送速率为 r,则每隔 1/r 秒一个令牌被加入到桶中;

假设桶最多可以存发 b 个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;

当一个 n 个字节的[数据包]到达时,就从令牌桶中删除 n 个令牌,并且数据包被发送到网络;

如果令牌桶中少于 n 个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外;

两种限流

1、DelayingLimiter【限流延迟访问】

2、ErroringLimiter【限流错误返回】

Middleware

因为 endpoint 的封装,我们在使用 go-kit 提供的其它中间件时十分简单。下面就是一个完整的限流延迟中间件

把已有的 endPoint 外再包一层 endPoint,再从最外层向内一层层调用

func NewDelayingLimiter(limit Waiter) endpoint.Middleware {
	return func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, request interface{}) (interface{}, error) {
			if err := limit.Wait(ctx); err != nil {
				return nil, err
			}
			return next(ctx, request)
		}
	}
}

使用延迟限流

把之前我们的 bookListEndPoint 进行更改

添加限流处理前的 bookInfoEndPoint

bookServer := new(BookServer)
bookInfoHandler := grpc_transport.NewServer(
	makeGetBookInfoEndpoint(),
	decodeRequest,
	encodeResponse,
)
bookServer.bookInfoHandler = bookInfoHandler

添加限流后的代码

bookInfoEndPoint := makeGetBookInfoEndpoint()
// 创建限流器 1r/s
limiter := rate.NewLimiter(rate.Every(time.Second*1), 1)
// 通过DelayingLimiter中间件,在bookInfoEndPoint 的外层再包裹一层限流的endPoint
bookInfoEndPoint = ratelimit.NewDelayingLimiter(limiter)(bookInfoEndPoint)

bookInfoHandler := grpc_transport.NewServer(
	bookInfoEndPoint,
	decodeRequest,
	encodeResponse,
)
bookServer.bookInfoHandler = bookInfoHandler 

测试

fmt.Println("请求服务: ", instanceAddr, "当前时间: ", time.Now().Format("2006-01-02 15:04:05.99"))

我们把之前的客户端代码加上输出请求的时间点, 查看下多次请求的情况

请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:20.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:20.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:21.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:22.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:23.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:24.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:25.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php
请求服务:  127.0.0.1:50051 当前时间:  2018-04-28 15:47:26.8
        获取书籍详情
        bookId: 1  =>  bookName: 21天精通php

Process finished with exit code 0
  • ratelimit
    1 引用
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    491 引用 • 1383 回帖 • 368 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...