Sentinel Dashboard 控制台配置详解
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。
Sentinel 控制台包含如下功能:
查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
规则管理和推送:统一管理推送规则。
鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。
阿里云提供了 企业级的 Sentinel 控制台,应用高可用服务 AHAS,对外收费,比较贵,但是具备Sentinel 数据持久化功能,开源版是不具备该功能的,我们也可以对sentinel进行改造让他支持持久化。
实时监控
**监控接口的通过的QPS和拒绝的QPS **。同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在”实时监控”下。
注意: 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
注意:请确保 Sentinel 控制台所在的机器时间与自己应用(服务)的机器时间保持一致,否则会导致拉不到实时的监控数据。
簇点链路
簇点链路用来显示微服务所监控的API,簇点链路的信息是存储在客户端内存中的,Sentinel会去实时拉取客户端的资源状态,如果客户端服务器一旦重启,数据就会丢失。
数据视图
该页面有2种显示方式:树形视图、列表视图。
树形结构视图
列表视图
流控规则
1)新增流控规则
资源名:需要进行限流的资源对象
针对来源:流控来源,default 不区分调用来源
阈值类型:QPS、并发线程数
单机阈值:限流阈值
是否集群:如果是集群对象,这里要勾上,如果是单机,不勾
2)限流阈值类型
流量控制主要有两种统计类型,一种是统计并发线程数,另外一种则是统计 QPS。
QPS(Query Per Second):每秒请求数,就是说服务器在一秒的时间内处理了多少个请求。
并发线程数:1秒内能处理多少个线程
举个例子
QPS:假设一个请求响应时间是0.2秒,那么1秒的QPS就是5,如果我们设置1秒只允许5个请求的话,新的请求进来就就会被拒绝。
线程数:1秒内只允许5个线程,此时5个线程的时间窗口(运行周期,请求处理时间)是2秒,如果有新的请求进来会直接被拒绝,因为在1秒内5个线程都占满了。
3)QPS限流测试
QPS单机阈值大于1,也就是我们1秒钟访问2次接口就会限流
访问测试:http://localhost:8080/springBootSentinelException
如图所示,这个图是sentinel默认的流控提示,我们可以通过实现sentinel接口来自定义异常处理。
BlockException异常统一处理
springwebmvc接口资源限流入口在HandlerInterceptor的实现类AbstractSentinelInterceptor的preHandle方法中,对异常的处理是BlockExceptionHandler的实现类
自定义BlockExceptionHandler 的实现类统一处理BlockException
1 | package com.javaxing.springsentineldemo.config; |
再次访问测试:
4)流控模式
流控模式分为3种:直接模式、关联模式、链路模式。
直接模式
资源调用达到设置的阈值后直接被流控抛出异常。
关联模式
关联模式:当关联资源达到流控阈值后,就对当前资源进行流控。
使用场景:当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联,如在数据库中对同一个字段进行读操作和写操作的资源争抢,或如 当一台服务器连接到MySQL后,多个操作共同复用同一个连接,就会存在资源争抢。
使用关联模式可以让关联资源具备有更高的优先级,当关联资源达到了阈值,就会流控当前资源,来降低 关联资源的压力。
关联模式测试
我们接下来直接用jmeter来进行压测,每秒3个请求,请求接口 为 关联的资源接口,这样的话 当关联资源接口每秒超过2个QPS后,springBootSentinelException资源就会被限流。
当我们开始压测关联资源(1秒3个QPS),我们在去访问springBootSentinelException接口,会直接提示限流。
链路模式
新增链路模式
当queryOrderInfo达到阈值QPS 2后,就会对 入口资源:test1 进行流控。这里和关联模式是反过来的。
链路模式失效问题
链路模式失效有2个主要原因:
1、高版本收敛链路
2、FlowException异常
高版本收敛链路问题
从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,导致链路限流不生效。
从1.7.0版本开始,官方在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context,将其配置为false即可根据不同的URL进行链路限流。
需要在yml中配置spring.cloud.sentinel.web-context-unify属性为false
1 | # 将其配置为 false 即可根据不同的 URL 进行链路限流 |
FlowException异常
原因分析:
- Sentinel流控规则的处理核心是 FlowSlot, 对getUser资源进行了限流保护,当请求QPS超过阈值2的时候,就会触发流控规则抛出FlowException异常
- 对getUser资源保护的方式是@SentinelResource注解模式,会在对应的SentinelResourceAspect切面逻辑中处理BlockException类型的FlowException异常
解决方案: 在@SentinelResource注解中指定blockHandler处理BlockException
1 |
|
5)流控效果
当QPS超过阈值后,就会触发流控。流控的方式有三种:快速失败(直接拒绝)、Warm UP(预热模式,平缓提升)、匀速排队(排队等待)。
- 快速失败:达到阈值后,直接会拒绝并抛出FlowException异常
- Warm UP:对于超过阈值的请求也是会拒绝并抛出异常,但是会阈值平缓上升,慢慢的提高阈值
- 匀速排队:让所有的请求 进行排队消费,先进先出
快速失败
默认流控的处理方式,达到阈值后,直接会拒绝并抛出FlowException异常,适用于已经进行过压测,明确知道系统的处理能力。
Warm UP 预热模式
Warm UP 预热模式,为了避免突然大量的请求直接把系统打崩溃,我们可以采用预热模式。
通过Warm UP可以让流量缓慢增加,平缓提升到阈值的上限,给系统一个预热时间,避免一下子大量的请求把服务器打崩溃。
冷加载因子
codeFactor 默认是3,即请求 QPS 从 threshold(阈值) / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
举个例子:阈值如果设置10,那么这个阈值一开始就会被动态的调整成3,然后逐步增长,最终到达阈值上限 10 。
实验验证
我们对springBootSentinelSuccess进行流控限制,流控效果为Warm Up ,让它在5秒内 缓缓的从3 动态过度到10
通过jmeter进行压测
一开始的时候,10个请求只允许通过3个,丢弃7个,缓慢的平湖南上升,直到阈值上限。
匀速排队
匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER
)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
匀速排队:所有处理不了的请求都会按顺序排队,慢慢的进行消费,直到队列清空。
如果一下子请求太多,我们无法处理的话,默认情况下会拒绝掉多余的请求,而如果我们不想拒绝掉无法处理的请求的话,我们可以让他进行排队等待,等待可以处理的时候在进行消费。
注意:超时时间不可以太短,太短的话会导致排队的请求来不及处理就被拒绝了。
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
实验验证
流控规则
JMeter 压测
压测结果
每秒13个请求,但是只允许通过10个请求,还有3个请求会进入排队,以此类推。
熔断规则
1)慢调用比例
最大RT:单个请求最长的响应超时时间
熔断时长:对该资源的熔断时长
统计时长:时间窗口的延迟 ,默认1秒,我们一般也是以1秒为单位
比例阈值:触发熔断的个数比例,如 最小请求5个,阈值0.6,那么触发熔断的个数最少必须达到3个(5*0.6)
最小请求数:触发熔断器的最小请求数量
达到慢调用熔断的限制必须满足2个条件:
- 触发熔断的个数必须达到 比例阈值
- 统计时长必须超过最小请求数
慢调用实验验证
controller
1 |
|
我们在controller里面延时200毫秒,请求该接口的延时必然会超过熔断策略RT时间
JMeter压测
如图所示,前面请求正常,随着业务逻辑时间超过RT的次数后,就触发熔断策略。
当下一个请求进入sentinel后,会判断状态是否为open状态,如果是,就判断 当前时间是否超过 熔断时间(超时时间),如果超过就把状态变成halfOpen状态 并进入业务逻辑。
这也是为什么 突然有一个请求可以通过 并执行业务逻辑的原因。
慢调用熔断器的源码执行流程
- 当一个请求进入服务器后,会先被sentinel管控
- 如果不符合熔断规则,直接放行
- 如果符合了熔断规则,熔断器就会从close状态变成 open状态
- 当下一个请求进入sentinel后,会判断状态是否为open状态
- 如果是,就判断 当前时间是否超过 熔断时间(超时时间)
- 如果超过就把状态变成halfOpen状态 并进入业务逻辑
- 如果不超过,返回false执行熔断
- 如果不是,就返回 flase 执行熔断
- 如果是,就判断 当前时间是否超过 熔断时间(超时时间)
- 当业务逻辑执行结束后判断 业务执行的时间是否 超过熔断阈值
- 如果超过了,就会把熔断器从halfOpen变成open状态
- 如果没有超过,就把熔断器都变成close 状态
慢调用源码分析
进入cb.tryPass(context)方法
retryTimeoutArrived方法
fromOpenToHalfOpen方法
当业务逻辑结束后,会执行exit方法
2)异常比例
- 在统计时间内异常请求次数超过比例阈值就会触发熔断器。
比例阈值:如 0.6,那么在1秒内(统计时长) 异常数量达到3个就会触发熔断器。(5*0.6)
1 | AtomicInteger atomicInteger = new AtomicInteger(); |
JMeter压测
3)异常数
- 在统计时间内异常请求次数超过阈值就会触发熔断器。
在统计时长(10秒)内,最少有5个请求并且有3个请求异常,就会触发熔断器。
JMeter压测
热点规则
1)什么是热点规则
我们把经常被访问的数据称为 热点数据,如果我们需要对热点数据设置流控的话,可以对其设置 热点策略。
同一个请求 resA,携带的参数不同 有 axb、abc、xs,我们可以根据携带的参数进行流控
注意:
- 热点规则需要使用@SentinelResource(“resourceName”)注解,否则不生效,尤其是controller上做热点规则是不会生效的
- 参数必须是7种基本数据类型才会生效
2)实验验证
1.1 @SentinelResource设置sentinel资源
我们为springBootSentinelSuccessHotData 设置成sentinel资源。
1 |
|
1.2 设置热点策略
1、资源名为springBootSentinelSuccessHotData 的参数索引0(第一个参数),1秒内只允许访问3次,超过就会触发流控
2、由于添加了额外策略,该策略限制:当第一个参数为10086并且类型必须为int,符合策略的1秒内只允许访问1次
实验测试
- id为10086的 1秒内只允许访问一次
测试结果
系统规则
尽管我们做了很多策略,如 熔断策略、流控策略,但是当高并发大流量进入的时候,服务器负载太高处理不过来,为了避免服务器宕机,我们可以设置 系统规则策略,来保护机器的一个正常运行。
系统保护规则是从应用级别的入口流量进行控制,系统保护是保护整个应用级别,而并非应用下的某个资源。
规则策略有四个维度:Load、RT、入口 QPS 和线程数。
系统规则阈值类型
Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
举个例子:
授权控制规则(来源访问列表)
很多时候,我们需要根据调用者服务器来判断请求是否放行,此时我们就可以通过sentinel 来确定是否放行该服务器的请求。
授权控制规则有2个名单:白名单、黑名单。
1)配置授权规则
- resource:资源名,即限流规则的作用对象。
- limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB。
- strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。
我们可以根据资源名,去授权 调用的应用服务器名称,授权时 可以加入到白名单或黑名单。
若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
2)实现sentinelRequestOriginParser接口
由于sentinel并没有完善获取origin 来源的方法,所以我们需要自行完善。
1 | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; |
这里的serviceName 我们采取的是通过get 参数的形式携带过来,实际上可以通过很多种方式获得,这个可以自行拓展,主要是要告知sentinel 你的调用origin来源服务名即可。
集群流控规则
- 开源版的sentinel 集群流控是不完善的,这里并不推荐,如果需要使用该功能,需要自行修改开源源码完善该功能。
- 为什么不完善,完善的话,还要商业版的干嘛?
为什么要使用集群流控呢?假设我们希望给某个用户限制调用某个 API 的总 QPS 为 50,但机器数可能很多(比如有 100 台)。这时候我们很自然地就想到,找一个 server 来专门来统计总的调用量,其它的实例都与这台 server 通信来判断是否可以调用。这就是最基础的集群流控的方式。
另外集群流控还可以解决流量不均匀导致总体限流效果不佳的问题。假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 QPS,理想情况下整个集群的限流阈值就为 100 QPS。不过实际情况下流量到每台机器可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。因此仅靠单机维度去限制的话会无法精确地限制总体流量。而集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。
https://github.com/alibaba/Sentinel/wiki/%E9%9B%86%E7%BE%A4%E6%B5%81%E6%8E%A7
集群流控中共有两种身份:
- Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。
- Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)。
Sentinel 集群流控支持限流规则和热点规则两种规则,并支持两种形式的阈值计算方式:
- 集群总体模式:即限制整个集群内的某个资源的总体 qps 不超过此阈值。
- 单机均摊模式:单机均摊模式下配置的阈值等同于单机能够承受的限额,token server 会根据连接数来计算总的阈值(比如独立模式下有 3 个 client 连接到了 token server,然后配的单机均摊阈值为 10,则计算出的集群总量就为 30),按照计算出的总的阈值来进行限制。这种方式根据当前的连接数实时计算总的阈值,对于机器经常进行变更的环境非常适合。
启动方式
Sentinel 集群限流服务端有两种启动方式:
- 独立模式(Alone),即作为独立的 token server 进程启动,独立部署,隔离性好,但是需要额外的部署操作。独立模式适合作为 Global Rate Limiter 给集群提供流控服务。
- 嵌入模式(Embedded),即作为内置的 token server 与服务在同一进程中启动。在此模式下,集群中各个实例都是对等的,token server 和 client 可以随时进行转变,因此无需单独部署,灵活性比较好。但是隔离性不佳,需要限制 token server 的总 QPS,防止影响应用本身。嵌入模式适合某个应用集群内部的流控。
云上版本 AHAS Sentinel 提供开箱即用的全自动托管集群流控能力,无需手动指定/分配 token server 以及管理连接状态,同时支持分钟小时级别流控、大流量低延时场景流控场景,同时支持 Istio/Envoy 场景的 Mesh 流控能力。