+
80
-

怎么对系统进行分布式限流设计?

请问大型系统如何进行分布式限流设计?

比如阿里、百度、腾讯是怎么做的

网友回复

+
0
-

单台服务器限流

1、时间间隔算法

先讨论最简单的场景,单台机器,用什么方式来限制流量?通常一个非常简单的做法,就是根据请求的时间间隔来限流。

描述如下:例如每秒100次,那我用时间戳做key, 每次请求对这个key进行自增操作,并判断这个value值是否会会大于100这个值,如果是大于,则触发限流逻辑。

存在问题:

1)如果在t=0.9s~1.0s这0.1S内,收到了100次请求,不会触发限流。如果t=1.0S到1.1S内,收到100次请求,由于是一个新的时间key,也不会触发限流,那在t=0.2S到1.2S这1S时间内,则收到了200次请求,超出了限流值。

2)或者你会想到,那我把时间粒度再切分细一些,按0.1S允许10个请求。这样又会引入另一个问题。我如果在1S内,前0.9S没有请求,最后0.1S如果来100个,那就会有90个被限制,无法应对突发流量问题。

2、令牌桶算法

这是网络中处理流控的一个经典算法。令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

分布式服务器限流

现在把问题扩大一些来讨论。如果你的业务系统不是一台机器,会有多台机器,假设有四台机器,限流系统假设还是一台机器,这种场景如何设计?

方案一

每次业务系统请求的时候,都来限流系统中询问一下,是否已经超过流量限制。这样本质上跟单机系统没有什么区别,存在的问题在于:网络开销是不是太大,有没有必须每次都去询问?

方案二

三台业务机器,能否开始的时候,就把每台机器分配一个配额,然后每台业务机器自己通过本地来做限流。这种方案问题也比较明显:如果其中某如机器挂了,那就是无法自动适配总流量,会让系统的流量限制变成更小,例如原先每台机器限制25,总共限100,那死了一台机器,则总流量会被限制成75。

方案三

令牌桶算法的延伸。每秒去请求一次服务器,去服务器端拿令牌数。令牌数则是由限流系统来分配。初始值的时候,可以按照平均分的方式来分配。例如:第t=0s时刻,A、B、C、D服务器都去获取令牌,每个业务服务都能获取25个令牌。每次令牌快消费完的时候,去向限流服务请求令牌。

两个异常场景:

1、如果四台服务器流量不平均,如何解决?

2、如果某台机器挂了,如何将限流额度分摊到其他机器?

解法一:

通过在限流服务中去统计每个服务的请求次数,去按比例分配令牌。例如:过去10S钟内,A、B、C、D去请求的次数分别为20、10、5、5。那下一个10S周期内,则A、B、C、D来请求的时候,令牌数就按照20/40,10/40,5/40,5/40这个数量来分配。如果某台机器挂了,那么在一个周期内他的请求次数必为0,那必须额度会被其他机器所分掉。问题1、2得到解决。

解法二

解法一曾经拿出去与人讨论过,被挑战到:我作为限流系统,我为什么还需要关注谁来请求,我这样是不是设计会非常复杂? 于是有了如下方案:按一个经验值来算,例如每次请求时候,就直接分配20的配额。然后谁用得快,谁就勤快些过来取,这样是不是就比较好的解决了限流的复杂性问题。

限流系统单点问题

上一个问题中,还假设限流系统是单点,如何解决限流系统的可靠性问题?

方案一

通过主备方式:两台服务器做成主备,通过客户端心跳感知的方式进行主备切换。 存在问题:如果主挂了,那么系统访问备。但如果只是某一次心跳抽风,那某台机器可能就访问到备机了,那么此时,就可能主备都在工作,限流逻辑失效!

方案二

主备两个服务,只允许一个进行工作,引用分布式锁解决问题。 通过主备启动的时候,抢占到分布式锁的服务优先对外服务。通过引入一个分布式锁来解决主备同时工作的问题。

扩展性

如果需要访问的节点足够多的情况下,限流服务如果扛不住,如何扩容? 简单的办法,可以通过再多一层的方式。我一层作为总的配额,然后二层水平扩展为多实例,通过多实例对外服务。
我知道答案,我要回答