前言
本篇文章介绍 Sentinel
的部署以及如何使用 Sentinel
进行服务的流量控制,希望观众老爷们多多支持并在评论区批评指正。
1. 部署并注册服务
1.1. 安装
Sentinel
和 Nacos
一样,都是独立安装和部署的 ,Sentinel下载[1]。注意我们下载完毕之后是一个 jar
包。
接下来我们就是开始 Sentinel
的安装和部署:
-
在项目中创建一个文件夹 sentinel
,将我们下载的jar
包,复制进去:

-
点击编辑配置-> 添加 JAR
应用程序 -> 命名服务名称并选择JAR
包路径 -> 并添加环境变量指定Sentinel
服务端口。

-
运行 JAR
包,访问Sentinel
监控页面,用户名和密码都为sentinel
,访问地址localhost:8858
。

进入控制台后,我们发现什么也没,那么就需要将我们的服务连接到 Sentinel
控制台。
1.2. 将服务连接至 Sentinel
注意:先启动 nacos
。
将 book-service
连接至 Sentinel
-
首先在 book-service
中引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
-
在 book-service
的配置文件中配置sentinel
。

-
启动 book-service
,在Sentinel
监控页面查看服务是否出现。

我们发现注销后重新登录 book-service
依旧没有出现,这是怎么回事?原来服务连接至 sentinel
并不会上来就连接,而是当我们访问这个服务的时候,才会连接到 Sentinel
(懒加载机制,减少资源的消耗)。
那么我们就访问一次 localhost:8301/book/1

然后再查看 Sentinel
监控页面,就发现 book-service
已经出现了,我们可以查看实时监控,我们刚刚的请求:

现在我们就可以在Sentinel
控制台中对我们的服务运行情况进行实时监控了,可以看到监控的内容非常的多,包括时间点、QPS
(每秒查询率)、响应时间等数据。
然后按照上面的方式,将我们的所有微服务注册到 sentinel
中去:

2. 流量控制
2.1. 限流策略及算法
前面我们完成了对 Sentinel
的搭建与连接,接着我们来看 Sentinel
的第一个功能,流量控制.
我们的机器不可能无限制的接受和处理客户端的请求,如果不加以限制,当发生高并发情况时,系统资源将很快被耗尽。为了避免这种情况,我们就可以添加流量控制(也可以说是限流)当一段时间内的流量到达一定阈值的时候,新的请求将不再进行处理,这样不仅可以合理地应对高并发请求,同时也能在一定程度上保护服务器不受到外界的恶意攻击。
那么要实现限流,正常情况下,我们该采取什么样的策略呢?
-
方案一:「快速拒绝」,既然不再接受新的请求,那么我们可以直接返回一个拒绝信息,告诉用户访问频率过高。 -
方案二:「预热」,依然基于方案一,但是由于某些情况下高并发请求是在某一时刻突然到来,我们可以缓慢地将阈值提高到指定阈值,形成一个缓冲保护。 -
方案三:「排队等待」,不接受新的请求,但是也不直接拒绝,而是进队列先等一下,如果规定时间内能够执行,那么就执行,要是超时就算了。
针对于是否超过流量阈值的判断,这里我们介绍4种算法:
-
「漏桶算法」
顾名思义,就像一个桶开了一个小孔,水流进桶中的速度肯定是远大于水流出桶的速度的,这也是最简单的一种限流思路:
我们知道,桶是有容量的,所以当桶的容量已满时,就装不下水了,这时就只有丢弃请求了。
利用这种思想,我们就可以写出一个简单的限流算法。
-
「令牌桶算法」
只能说有点像信号量机制。现在有一个令牌桶,这个桶是专门存放令牌的,每隔一段时间就向桶中丢入一个令牌(速度由我们指定)。当新的请求到达时,将从桶中删除令牌,接着请求就可以通过并给到服务,但是如果桶中的令牌数量不足,那么不会删除令牌,而是让此数据包等待。
可以试想一下,当流量下降时,令牌桶中的令牌会逐渐积累,这样如果突然出现高并发,那么就能在短时间内拿到大量的令牌,那么我们服务也会吃不消。所以我们可以做一个检测,当流量下降时逐级减少令牌的增加。
-
「固定时间窗口算法」
我们可以对某一个时间段内的请求进行统计和计数,比如在14:15
到14:16
这一分钟内,请求量不能超过100
,也就是一分钟之内不能超过100
次请求,那么就可以像下面这样进行划分:
虽然这种模式看似比较合理,但是试想一下这种情况:
-
-
14:15:59 的时候来了100个请求 -
14:16:01 的时候又来了100个请求
出现上面这种情况,符合固定时间窗口算法的规则,所以这200个请求都能正常接受,但是,如果你反应比较快,应该发现了,我们其实希望的是60秒内只有100个请求,但是这种情况却是在3秒内出现了200个请求,很明显已经违背了我们的初衷。因此,当遇到临界点时,固定时间窗口算法存在安全隐患。
-
「滑动时间窗口算法」
相对于固定窗口算法,滑动时间窗口算法更加灵活,它会动态移动窗口,重新进行计算:
虽然这样能够避免固定时间窗口的临界问题,但是这样显然是比固定窗口更加耗时的。
2.2. 演示流量控制
针对 borrow-service
进行演示:
了解完限流策略和判定方法之后,我们在 Sentinel
中进行实际测试一下,打开管理页面的簇点链路模块:

点击流控
,会看到让我们添加流控规则:

-
阈值类型:QPS就是每秒钟的请求数量,并发线程数是按服务当前使用的线程数据进行统计的。 -
流控模式:当达到阈值时,流控的对象,这里暂时只用直接(直接表示当前接口)。 -
流控效果:就是我们上面所说的三种方案。
2.2.1. 流控效果的演示
-
这里我们限制请求数,针对当前请求来演示第一种效果:设置阈值类型为 QPS
,单机阈值为1
,流控模式为直接(也就是当前资源),流控效果为快速失败(当达到阈值,不再接收以后的请求,返回拒绝信息)。

然后我们请求这个 borrow/{uid}
,快速点击:就会返回失败信息。

-
当我们改变流控效果为 Warm up
(预热模式),其他设置不改变时:假设预热时长为5s
,那么请求限制阈值会在5s
内增长到10
。

这样的效果时,会随着预热时长,慢慢达到最终阈值,有一个缓冲时间。
-
当我们改变流控效果为排队等待模式时,我们需要设置超时时间,当超过设定的超时时间时不对新的请求进行处理,但是也不直接拒绝,而是进队列先等一下,如果规定时间内能够执行,那么就执行,要是超时就算了。(超时时间单位 ms
)

这里我们使用 apifox
,演示这个效果,因为我们使用浏览器进行演示的话,请求不会超过的。
2.2.2. 流控模式的演示
最后我们来看看这些流控模式有什么区别:

-
直接:只针对于当前接口。 -
关联:当其他接口超过阈值时,会导致当前接口被限流。 -
链路:更细粒度的限流,能精确到具体的方法。
-
直接的流控模式我们已经演示过了,接下来我们就演示一下关联模式,我们设置关联的资源接口为自带的 /error
,流控效果为快速失败,单击阈值为1
。

然后请求 /error
接口,通过 apifox
进行请求,设置请求两次 error
后,请求一次 borrow/1

我们可以看到快速请求两次 /error
后,虽然 /error
接口正常,但是 /borrow/{uid}
却被流控了,也就是说 /error
造成的后果由 /borrow/{uid}
承担。
-
然后我们演示链路模式,它能够更加精准的进行流量控制。链路流控模式指的是,当从指定接口资源请求达到限流条件时,开启限流。
这里得先讲解一下@SentinelResource
注解的使用,我们可以对某一个具体方法进行限流控制,无论是谁在何处调用了它。当该方法上标注@SentinelResource
注解后,就会进行监控,比如我们这里创建两个请求映射,都来调用 BorrowService
的被监控方法 getUserBorrowDetailByUid(uid)
:

然后我们为 getUserBorrowDetailByUid(uid)
方法上添加@SentinelResource
注解,对该方法进行监控:

接着我们在 borrow-service
的 application.yml
中添加配置,然后重启服务。

接着我们对这个接口请求一次 borrow borrow2
,sentinel
簇点链路就监控到了我们标注@SentinelResource
注解的具体方法了。

然后我们对该方法(getBorrow
)添加流控,流控模式为直接模式。

然后我们请求这两个接口 borrow borrow2
,可以发现无论请求那个接口,超过阈值都会被限流,但是返回的不是拒绝信息,而是错误。

然后我们选择链路模式,链路选项实际上就是决定只限流从哪个方向来的调用,比如我们只对borrow2
这个接口对getUserBorrowDetailByUid
方法的调用进行限流,那么我们就可以为其指定链路:

然后我们会发现,限流效果只对我们配置的链路接口有效,而其他链路是不会被限流的。
2.2.3. 根据系统资源,对该服务整体进行限流
除了直接对接口进行限流规则控制之外,我们也可以根据当前系统的资源使用情况,是否对请求某个服务的所有请求进行限流:

系统规则支持以下的模式:
-
「Load 自适应」(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。 -
「CPU usage」(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。 -
「平均 RT」:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。 -
「并发线程数」:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。 -
「入口 QPS」:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
这里我们就演示一下 CPU
模式:本机系统 CPU
在 10%
上下波动,我们就设置 CPU
阈值为 0.1
,然后进行请求,看是否会限流:

在快速点击下,超过了 CPU
阈值,borrow-service
整体被限流了。

「注意:」
系统规则在具体服务中,而不是针对所有的微服务。因为我们是在具体的服务的系统规则中进行设置的,只针对当前服务。而且在实际场景中,各个微服务分布在不同的主机中。
Reference
Sentinel下载: https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
原文始发于微信公众号(yanghi):SpringCloud Alibaba微服务之使用Sentinel进行流量控制
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/226563.html