Go 语言限流

        缓存、降级和限流是高并发保护高可用的手段。比如某个明星在微博上发了一条动态,短时间内其可能获得上亿次的转发量,这给微博的服务器造成了巨大的压力,甚至有短暂不可用的状态。解决方法无外乎紧急增加缓存,将不常用的特性临时降级,对资源进行限流,避免将后台服务打爆。

        限流是我们常用的在高并发下保护有限资源的手段。现在可能没有人去抢火车票了,但在 N 年前过年的时候,大家都会拼命地抢火车票,以至于把 12306 网站刷得不可用了。 12306 通过业务改造,扩容、分片以及排队等限流手段,降低了对服务器的压力,保证了网站可用。

        令牌桶和漏桶是常见的限流手段,可以帮助我们处理高并发的请求。

1. 基于令牌桶实现的限流库

        令牌樋算法是网络流量整行( traffic shaping) 和速率限制( rate limiting )中最常使用的一种算法。它不只是用来处理网络流量,我们在处理任意请求时,也可以使用它来控制处理请求的速率,并允许对一定范围内的突发请求进行处理。

        大小固定的令牌桶以恒定的速率源源不断地产生令牌,如下图所示:

        如果令牌不被消耗,或者令牌被消耗的速率小于其产生的速率,那么令牌桶中的令牌就会不断增多,直到把桶填满。后面新产生的令牌会从令牌桶中溢出,最后令牌桶中可以保存的最大令牌数永远不会超过桶的大小。

令牌桶的处理方式如下:

  • 假如用户配置的处理速率为 r,则每隔 1/r 秒就会将一个令牌加入令牌桶中。
  • 假设令牌桶最多可以存放 n 个令牌,如果新令牌到达时令牌桶已满,那么这个新令牌会被丢弃。
  • 当处理一个请求时,就从令牌桶中删除一个令牌。
  • 更广泛的,可以一次申请多个令牌,这可能是一次要处理多个请求,也可能是请求处理的权重不同,有的请求需要多个令牌。
  • 如果当前令牌桶中的令牌少于请求的令牌,则不会删除令牌,这个请求将被丢弃;或者,更好的方式是不丢弃请求,而是将其放入一个队列中缓存起来,以后再处理。

        可以看到,如果某个时间没有请求要处理的话,那么令牌桶中的令牌可能会积攒得非常多,甚至令牌桶满了。这时候,如果有大量突发请求,它们可能都能获取到令牌,一起按并发地处理。假设在短时间内需要处理大量的请求,在极端情况下,如果突发请求把令牌全取走了,那么之后即使是很小的并发请求,也获取不到令牌,它可能会被丢弃或者在队列中等待。这是令牌桶的一个特点,允许处理突发请求,但是从一个长周期来看,令牌桶的处理速率是恒定的。

1.1 x/time/rate

        golang.org/x/time/rate 是 Go 官方提供的一个基于令牌桶实现的限流库。

        这个库提供的 Limiter 可以控制事件发生的频率。假设令牌桶的容量为 b,每秒以固定的速率 r 填允,并且一开始令牌桶就被填满了。在很长的一段时间内,Limiter 限制令牌产生的速率是每秒 r 个,并且允许有最多 b 个突发事件。如果 b 是无穷大的,那么它就会被忽略。b 既是令牌桶的容量,也是允许一次获取的最大令牌数。

        Limiter 的零值也是有效的值,但是基本上没什么意义,因为它表示拒绝所有的事件。

        Limiter 有三个主要办法,即 Allow、Reserve、Wait,每个方法都会消耗一个令牌。它们的不同之处在于:

  • Allow --如果没有令牌可用,这个方法将直接返回 false,不会被拒绝
  • Reserve--如果没有令牌可用,这个方法将返回为未来可用令牌保留的一个对象Reservation,以及调用者要等待的时间。
  • Wait--如果没有令牌可用,这个方法将会被阻塞,直到获取到一个令牌,或者 Context 完成(被撤销)。

1.2 juju/ratelimit

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mindfulness code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值