官网:https://sentinelguard.io/zh-cn/docs/introduction.html
github:https://github.com/alibaba/Sentinel/wiki
sentinel是面向分布式服务的流量控制组件,以流量为切入点,进行流量控制、熔断降级、系统自适应保护等,保障系统的稳定性
基本概念
资源:如服务接口、方法、url等,资源根据设置的规则受sentinel保护
规则:针对资源设置的规则,包括限流规则、熔断降级规则、系统保护规则,规则可动态调整
sentinel 工作机制
定义资源,对资源进行实时统计、调用链路分析
根据预设规则,以及资源实时统计数据,对资源进行保护(限流、熔断降级、系统负载保护等)
sentinel dashboard可对系统进行实时监控
流量控制
# QPS流量控制:每秒请求数超过预设的阀值后,触发流量控制
直接拒绝:默认的流量控制措施,超过阀值后,直接拒绝新的请求
冷启动:系统请求长期处于低水位,当流量突然增加后,直接将系统拉升到该水位可能将系统压垮,
冷启动让流量缓慢增加值阀值,给系统预热时间,避免冷系统被压垮
匀速器:让系统匀速处理请求,类似于漏斗算法,主要用于处理间隔性突发流量,
某一时间突然收到大量请求,接下来处于空闲状态,可利用空闲时间继续处理请求,而不是直接拒绝请求
# 并发线程数流量控制:线程数超过阀值,拒绝请求
sentinel线程数限流不负责创建和管理线程池,而是简单统计当前请求上下文的线程个数,
如果超出阈值,新的请求会被立即拒绝
# 基于调用关系的流量控制
调用方限流:default(不区分调用者)、针对特定调用者({some_origin_name})、其他调用者(other)限流
同一个资源名可以配置多条规则,规则的生效顺序为:{some_origin_name} > other > default
调用链入口限流:一个资源有多个入口(entry、entry2),可选择只针对入口entry限流
关联流量控制:两个资源之间具有资源争抢或者依赖关系时,这两个资源便具有关联关系;
如两个资源分别对数据库的同一字段进行写操作,一个资源频繁进行写操作,
便会对另一资源的写操作产生影响,此时可考虑对频繁操作的资源进行限流
熔断降级
熔断降级:当调用链中的某个资源出现不稳定(响应超时、异常比例升高等),
此时需要让请求迅速失败,避免请求堆积,出现雪崩
# sentinel熔断降级
根据并发线程数降级:当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝,
堆积的线程完成任务后才开始继续接收请求
根据响应时间降级:当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,
直到过了指定的时间窗口之后才重新恢复
系统负载保护
单机环境下,当系统负载较高时,如果还让请求进入,可能会导致系统崩溃;
集群环境下,会将请求分发到其他系统,此时如果其他系统负载也很高,最终可能会导致整个集群不可用;
# sentinel保护措施
sentinel会让系统流量和系统负载达到一个平衡,保证系统在能力范围内处理更多的请求
NodelSelectorSlot:将资源之间的调用关系以树状结构存储,根据调用路径限流降级(同一个资源可以有多个调用路径)
ClusterBuilderSlot:存储资源的统计信息
# curl http://localhost:8719/origin?id=caller
id: nodeA
idx origin threadNum passedQps blockedQps totalQps aRt 1m-passed 1m-blocked 1m-total
1 caller1 0 0 0 0 0 0 0 0
2 caller2 0 0 0 0 0 0 0 0
origin:资源调用方
threadNum:线程数
passedQps:每秒通过的请求数
blockedQps:每秒阻塞的请求数
totalQps:每秒总的请求数
aRt:平均响应时间
1m-passed:1分钟通过的请求数
1m-bocked:1分钟阻塞的请求数
1m-total:1分钟总的请求数
StatisticSlot:采用高性能的滑动窗口数据结构(LeapArray
)实时统计指标数据
FlowSlot:根据资源统计信息,按照对资源设置的规则限流
DegradeSlot:根据统计信息(响应时间、异常比例等),对资源进行熔断降级
SystemSlot:动态调整系统入口流量,使之与系统设计的容量平衡,只对入口流量有效,对出口流量无效
************
集群流量控制
集群流控:限制单个用户对某个api的总调用次数为50次,该api在多个服务器上部署,此时可用一个server记录总的调用次数,其余服务处理请求前先与server通信,判断是否进行限流操作
集群流控可解决流量不均衡(总的流量没达到阀值,单机开始限流)导致总体限流效果不佳问题
集群限流客户端
com.alibaba.csp
sentinel-cluster-client-default
1.8.3
# 通过api将当前模式置为客户端模式
http://:/setClusterMode?mode=
mode=0:当前服务设置为客户端
mode=1:当前服务设置为服务端
mode=-1:关闭集群模式
# 配置客户端(ClusterClientConfig),除使用api配置外,也可使用sentinel dashboard配置
http://:/cluster/client/modifyConfig?data=
说明:config为json格式的clusterClientConfig
public class ClusterClientConfig {
private Integer requestTimeout;
public ClusterClientConfig() {
}
# 如果客户端连接远程服务端(token server)失败、或者通信失败,触发以下规则:
集群热点限流默认直接通过
普通集群限流会退化到local模式的限流
# token client连接server失败重试
连接意外断开时,token client会不断进行重试,每次重试的间隔时间以n*2000ms的形式递增
集群限流服务端:独立模式、内嵌模式
com.alibaba.csp
sentinel-cluster-server-default
1.8.3
# 集群限流服务端配置类型,可使用sentinel dashboard配置
namespace set:集群限流服务端服务的作用域(命名空间)
token client连接到token server会上报自己的命名空间(默认为project.name),
token server 会根据上报的命名空间名称统计连接数
transport config:通信相关配置,如server、port等
flow config:限流配置,如动窗口统计时长、格子数目、最大允许总QPS等
************
网关流量控制
sentinel支持对zuul、gateway等网关应用进行限流
实现原理
# 网关流控规则处理
GatewayRuleManager加载网关流控规则(GatewayFlowRule),
无论是否针对请求属性进行限流,都会将网关流控规则转化为热点参数规则(ParamFlowRule)
转换时根据请求属性配置,为网关流控规则设置参数索引(idx)
如果规则不针对请求属性,就在参数最后一个位置置入预设的常量,达到普通流控的效果
将转换后的热点参数规则存储在GatewayRuleManager中,与正常的热点参数规则隔离
# 请求过滤:SentinelGatewayFilter
外部请求进入网关时会用SentinelGatewayFilter过滤,执行route id、api分组匹配;
# 请求属性处理:GatewayFlowRule、ParamFlowRule
根据配置的网关流控规则来解析请求属性(用于热点参数限流),依照参数索引顺序组装参数数组,最终传入SphU.entry(res, args);
# 网关限流:GatewayFlowSlot
sentinel在slot chain中添加GatewayFlowSlot,从GatewayRuleManager提取网关限流规则,执行限流操作
************
热点参数限流
sentinel利用LRU策略统计热点参数,结合令牌桶算法来进行限流
# 热点数据限流:统计热点参数,根据配置的限流阈值与模式,对包含热点参数的资源进行限流
参数为商品id,统计一段时间内最常购买的商品ID并进行限制
参数为用户id,针对一段时间内频繁访问的用户ID进行限制
ParamFlowRule
public class ParamFlowRule extends AbstractRule {
private int grade = 1; //限流模式,默认为QPS
private Integer paramIdx; //热点参数的索引
private double count; //限流阈值
private int controlBehavior = 0; //流控效果:快速失败(默认)、匀速排队模式
private int maxQueueingTimeMs = 0; //最大排队等待时长(仅在匀速排队模式生效)
private int burstCount = 0; //应对突发流量额外允许的数量,默认为0
private long durationInSec = 1L; //统计窗口时间长度,默认为1s
private List paramFlowItemList = new ArrayList();
//额外参数选项,针对特定的参数单独限流,不受前面 count 阈值的限制
仅支持基本类型和字符串类型
private Map
************
来源访问控制
来源访问控制(黑白名单):根据调用方(origin)限制请求是否通过
如果配置白名单:白名单内的请求来源可通过,其余请求来源不通过
如果配置黑名单:黑名单内的请求来源不可通过,其余请求来源可通过
参数配置项:
resource:资源名,即限流规则的作用对象
limitApp:对应的黑名单/白名单,多个值用逗号间隔,如appA,appB
strategy:限制模式,AUTHORITY_WHITE(白名单模式,默认)、AUTHORITY_BLACK(黑名单模式)
配置示例
# 对资源test的访问设置白名单,只有来源为appA和appB的请求才可通过
AuthorityRule rule = new AuthorityRule();
rule.setResource("test"); //访问的资源
rule.setStrategy(RuleConstant.AUTHORITY_WHITE); //配置白名单规则
rule.setLimitApp("appA,appB"); //请求来源origin
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
熔断策略
# 慢调用比例:SLOW_REQUEST_RATIO,以慢调用比例作为阈值
慢调用:如果一个请求的响应时间需要大于设置的慢调用响应时间(RT),该请求统计为慢调用;
熔断触发:单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,
并且慢调用的比例大于阈值,在熔断时长内自动触发熔断
熔断恢复:在熔断时长后,熔断器进入探测恢复状态(half-open状态),
如果接下来的请求响应时间 < 设置的慢调用响应时间,则结束熔断
如果接下来的请求响应时间 > 设置的慢调用响应时间,则继续在熔断时长内保持熔断
# 异常比例 :ERROR_RATIO,以请求异常比例作为阀值,阈值范围是[0.0, 1.0]
异常请求:请求调用抛出异常,则该请求统计为异常请求
熔断触发:单位统计时长(statIntervalMs)内请求数目 > 设置的最小请求数目,
并且异常的比例 > 阈值,在熔断时长内自动被熔断
熔断恢复:在熔断时长后,熔断器进入探测恢复状态(HALF-OPEN 状态),
如果接下来的一个请求执行成功,则结束熔断;
如果请求执行失败,则继续在熔断时长内保持熔断
# 异常数:ERROR_COUNT,以异常请求数作为阀值
异常请求:请求调用抛出异常,则该请求统计为异常请求
熔断触发:单位统计时长(statIntervalMs)内异常请求 > 设置的异常请求数阀值,在熔断时长内自动被熔断
熔断恢复:在熔断时长后,熔断器进入探测恢复状态(HALF-OPEN 状态),
如果接下来的一个请求执行成功,则结束熔断;
如果请求执行失败,则继续在熔断时长内保持熔断
说明:异常降级仅针对业务异常,不统计sentinel block异常
DegradeRule
public class DegradeRule extends AbstractRule {
private int grade = 0; //熔断策略,支持慢调用比例(默认)、异常比例、异常数策略
private double count; //限流阀值
private int timeWindow; //熔断时间窗口
private int minRequestAmount = 5; //最小请求数
private double slowRatioThreshold = 1.0D; //慢调用比例阈值
private int statIntervalMs = 1000; //统计时间窗口,默认1s
public DegradeRule() {
}
AbstractRule
public abstract class AbstractRule implements Rule {
private String resource; //限流资源
private String limitApp; //调用来源、default、other
public AbstractRule() {
}
系统系适应保护目的:在系统不被压垮的前提下,保持系统的吞吐量
系统保护规则对应用级别的入口流量进行控制,仅对入口流量有效,对出口流量不起作用
从系统的总体负载(load)、cpu使用率、响应时间(RT)、入口QPS、线程数监控应用数据
SystemRule
public class SystemRule extends AbstractRule {
private double highestSystemLoad = -1.0D; //系统最高负载
private double highestCpuUsage = -1.0D; //cpu最高使用率
private double qps = -1.0D; //每秒请求数
private long avgRt = -1L; //平均响应时间
private long maxThread = -1L; //最大线程数
public SystemRule() {
}
AbstractRule
public abstract class AbstractRule implements Rule {
private String resource; //限制的资源
private String limitApp; //特定的资源、default、other
public AbstractRule() {
}