Skip to content

流量控制 匀速排队模式

Eric Zhao edited this page Jul 21, 2020 · 2 revisions

概述

Leaky Bucket 对应 流量整形 中的匀速器。它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过;否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。

这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。

例如,如果系统使用 Apache RocketMQ 来收发消息,系统在某个时间突然收到大量消息。我们希望以固定的速率来处理消息,而不是一下子拒绝这些消息。这个时候可以使用匀速器,也就是给消息排队。效果如下所示:

Uniform rate

Sentinel 匀速排队等待策略是 Leaky Bucket 算法结合虚拟队列等待机制实现的。

注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

示例

匀速排队流控 Demo 是一个如何使用匀速器的例子。这个例子示范的步骤如下:

  1. paceFlowRule() 这个函数里面,通过设置下面几个参数让匀速器生效:
rule.setGrade(RuleConstant.GRADE_QPS);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); // 流控效果:匀速排队模式
rule.setCount(10);
rule.setMaxQueueingTimeMs(20 * 1000); // 最长排队等待时间:20s

注意,当匀速器生效的时候,规则的限流类型一定是 RuleConstant.GRADE_QPS,否则该规则将不生效。当 count 设为 10 的时候,则代表一秒匀速的通过 10 个请求,也就是每个请求平均间隔恒定为 1000 / 10 = 100 ms,每一个请求的最长等待时间(maxQueueingTimeMs)为 20 * 1000ms = 20s。

  1. simulatePulseFlow() 这个函数,模拟了几乎同时到来的 100 个请求。

  2. 效果

我们来看一下运行结果:

下面的输出以逗号分隔,第一栏位通过的时间,第二栏为等待的时间
....
1528872403887 pass, cost 9348
1528872403986 pass, cost 9469
1528872404087 pass, cost 9570
1528872404187 pass, cost 9642
1528872404287 pass, cost 9770
1528872404387 pass, cost 9848
1528872404487 pass, cost 9970
done
pass:100 block:0

我们可以看到,这 100 个请求,都以匀速 100 ms 的速度依次通过,并且没有阻塞。

  1. 和默认的行为对比

我们通过 defaultFlowRule() 里,将该规则的流控效果设为 CONTROL_BEHAVIOR_DEFAULT(默认效果,快速失败),再发起同样的流量。这个时候检查结果,将会发现同样的流量,默认行为仅会通过 10 个。

Clone this wiki locally