微服务框架
【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】
微服务面试篇
文章目录
- 微服务框架
- 微服务面试篇
- 54 微服务篇
- 54.8 Sentinel的限流与Gateway的限流有什么差别?
- 54.8.1 限流与常见 限流算法
- 54.8.2 固定窗口计数器算法
- 54.8.3 滑动窗口计数器算法
- 54.8.4 令牌桶算法
- 54.8.5 漏桶算法
- 54.8.6 限流算法对比
54 微服务篇
54.8 Sentinel的限流与Gateway的限流有什么差别?
54.8.1 限流与常见 限流算法
限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。
限流算法常见的包括两种:
-
计数器算法,又包括窗口计数器算法、滑动窗口计数器算法
-
令牌桶算法(Token Bucket)
-
漏桶算法(Leaky Bucket)
54.8.2 固定窗口计数器算法
固定窗口计数器算法概念如下:
- 将时间划分为多个窗口,窗口时间跨度称为Interval (中文意思:间隔),本例中为1000ms;
像下面这样
横坐标 → 时间,单位 ms
划分成窗口
纵坐标可以理解为 QPS 值,即每秒的请求数
- 每个窗口维护一个计数器,每有一次请求就将计数器加一,限流就是设置计数器阈值,本例为3
QPS 超过3 ,就相当于超过 阈值 了
- 如果计数器超过了限流阈值,则超出阈值的请求都被丢弃。
每个窗口分别 统计
这个样子 有些问题
这样就相当于这一秒钟 内 ,通过了 6 个请求,这样就很容易导致 服务宕机,因为在1 秒内已经超出阈值 了
【这个就是 固定窗口,但其实真正的时间是没有界限 的】
54.8.3 滑动窗口计数器算法
滑动窗口计数器算法会将一个窗口划分为n个更小的区间,例如
- 窗口时间跨度Interval为1秒;区间数量 n = 2 ,则每个小区间时间跨度为500ms
这个时候就 相当于出现 了那么一些 更小 的区间
但这可不是 窗口,这只是 时间区间
- 限流阈值依然为3,时间窗口(1秒)内请求超过阈值时,超出的请求被限流
- 窗口会根据当前请求所在时间(currentTime)移动,窗口范围是从(currentTime-Interval)之后的第一个时区开始,到currentTime所在时区结束。
【举个栗子】
200 ms、 400 ms、900 ms 来的,所以前两个肯定在第一个时间区间,第三个请求 在第二个 时间区间
现在的滑动窗口 范围,是从当前时间 900ms, 900 - 1000 = -100,即从第一个 时区开始,到900 所在的时区【即前两个】
如果请求 当前时间为1250ms
滑动窗口 就是这个样子
计算这个范围内 总的请求量
这样就解决了固定 窗口的问题
但还是有有问题的 情况,比如下面这样
1250 - 2100 确实是 < 1s ,但是有4 个请求,但是滑动窗口 却只有两个,意思就是已经超出阈值了,但是并没有发现,这样就出事儿了
其实也可以通过把 窗口划分得更细,来解决。。
即窗口划分得越细,限流的效果就越准确【但是始终会出现“ 碰巧情况”,就是达不到 绝对准确】
54.8.4 令牌桶算法
令牌桶算法说明:
一个桶, 里面可以存储令牌
而且这个令牌是以固定速率 去生成 的
-
以固定的速率【“限流的值”】生成令牌,存入令牌桶中,如果令牌桶满了以后,多余令牌丢弃【即桶中令牌的数量不会超过 “阈值”】
-
请求进入后,必须先尝试从桶中获取令牌,获取到令牌后才可以被处理
“要过是吧,先拿令牌”
拿到令牌了 ,OK,放行
- 如果令牌桶中没有令牌,则请求等待或丢弃
但是还是有个 “问题”,思考这样一个情况
如果每秒钟生成 5 个令牌,第1 秒钟生产 了5 个令牌进桶,但是第一秒内,一个请求也没有,这5 个令牌就会存起来,OK,第2 秒钟, 突然来了 10个请求
这样的话,前 5个请求瞬间就过去了,然后第2 秒还会生成 5个令牌,所以第二秒内, 10 个请求全过去了
好家伙, 这样就 超出阈值 了
- 问题:超出了阈值
- 优势:能 应对突发请求
54.8.5 漏桶算法
漏桶算法说明:
一个存请求的桶
- 将每个请求视作"水滴"放入"漏桶"进行存储;
- "漏桶"以固定速率向外"漏"出请求来执行,如果"漏桶"空了则停止"漏水”;
- 如果"漏桶"满了则多余的"水滴"会被直接丢弃。
-
可以理解成请求在桶内排队等待
-
优势:可以应对突发请求
-
相对于 令牌桶 更加平滑
Sentinel在实现漏桶时,采用了排队等待模式:
让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。并发的多个请求必须等待,预期的等待时长 =最近一次请求的预期等待时间 + 允许的间隔。如果请求预期的等待时间超出最大时长,则会被拒绝。
例如:QPS = 5,意味着每200ms处理一个队列中的请求;timeout = 2000,意味着预期等待超过2000ms的请求会被拒绝并抛出异常
如果同一时刻 第12 个请求也来了,它的预期等待时长 就会超过2000ms,它会被拒绝
令牌桶 和 漏桶对比
54.8.6 限流算法对比
因为计数器算法一般都会采用滑动窗口计数器,所以这里我们对比三种算法:
对比项 | 滑动时间窗口 | 令牌桶 | 漏桶 |
---|---|---|---|
能否保证流量曲线平滑 | 不能,但窗口内区间越小,流量控制越平滑 | 基本能,在请求量持续高于令牌生成速度时,流量平滑。 但请求量在令牌生成速率上下波动时,无法保证曲线平滑 | 能,所有请求进入桶内,以恒定速率放行,绝对平滑 |
能否应对突增流量 | 不能,徒增流量,只要高出限流阈值都会被拒绝。 | 能,桶内积累的令牌可以应对突增流量 | 能,请求可以暂存在桶内 |
流量控制精确度 | 低,窗口区间越小,精度越高 | 高 | 高 |
OK,现在来回答我们的问题
Sentinel的限流与Gateway的限流有什么差别?
问题说明:考察对限流算法的掌握情况
难易程度:难
参考话术:
限流算法常见的有三种实现:滑动时间窗口、令牌桶算法、漏桶算法。Gateway则采用了基于Redis实现的令牌桶算法。
而Sentinel内部却比较复杂:
- 默认限流模式是基于滑动时间窗口算法
- 排队等待的限流模式则基于漏桶算法
- 而热点参数限流则是基于令牌桶算法
此时,如果面试官追问滑动时间窗口、令牌桶、漏桶算法原理,则根据上一节内容来回答。【妙啊】