十分钟搞懂阿里Sentinel核心源码(上)

简介: 十分钟搞懂阿里Sentinel核心源码(上)

简介


Sentinel提供了丰富的限流、熔断功能。它支持控制台配置限流、熔断规则,支持集群限流,并可以将相应服务调用情况可视化。

本文主要分析Sentinel的限流功能源码。


Sentinel会进行流量统计,执行流量控制规则。而统计数据的展示和规则的设置在 sentinel-dashboard 项目中,这是一个 Spring MVC 应用,有后台管理界面,我们通过这个管理后台和各个应用进行交互。

当然,你不一定需要 dashboard,仅仅使用 sentinel-core,它会将统计信息写入到指定的日志文件中,通过该文件内容来了解每个接口的流量情况。这时只是使用到了 Sentinel 的流量监控功能。


dashboard 应用默认不持久化数据,它的所有数据都在内存,所以 dashboard 重启意味着所有数据都会丢失。你应按需要定制化 dashboard,如至少你应该要持久化规则设置,QPS 数据非常适合存放在时序数据库中,当然如果你的数据量不大,存 MySQL 也问题不大,定期清理一下过期数据即可,因为大部分人应该不会关心一个月以前的 QPS。


Sentinel 的核心将不同 Slot 按序串在一起(责任链模式),从而将不同功能(限流、降级、系统保护)组合在一起。核心结构:image.png

slot chain 其实可以分为两部分


统计数据构建部分(statistic)


判断部分(rule checking)


Sentinel 的数据统计


数据统计模块的内容,这样读者在后面看到相应的内容的时候心里有一些底。这节内容还是比较简单的,当然,如果你希望立马进入 Sentinel 的主流程,可以先跳过这一节。


Sentinel 的定位是流量控制,它有两个维度的控制,一个是控制并发线程数,另一个是控制 QPS,它们都是针对某个具体的接口来设置的,其实说资源比较准确,Sentinel 把控制的粒度定义为 Resource。


要做控制,首先就要先做统计,它要知道当前接口的 QPS 和并发是多少,进而判断一个新的请求能不能让它通过。

数据统计的代码在


StatisticNode

image.png

QPS 数据使用了滑动窗口:

image.png

保存最近60秒的统计信息。windowLengthInMs 故意设置为1000毫秒,表示每秒每个桶,这样我们就可以获得每秒的准确统计信息。

image.png

线程数量的计数器,即统计并发量

image.png

可知,Sentinel 统计了 秒 和 分 两个维度,现在看其实现类

ArrayMetric

Sentinel中的基本度量标准类,使用内部 BucketLeapArray。

image.png

属性

以分钟维度统计的使用来说,使用子类 BucketLeapArray 实现。

image.png

构造器

image.png

LeapArray

字段

image.png

条件(谓词)更新锁,仅在不使用当前桶时使用。

image.png

内部核心数组 array,它的长度为 60,就是有 60 个窗口,每个窗口长度为 1 秒,一分钟走完一轮。然后下一轮开启“覆盖”操作。

image.png

每个窗口是一个 WindowWrap 类实例。


添加数据的时候,先判断当前走到哪个窗口了(当前时间(s) % 60 即可),然后需要判断这个窗口是否是过期数据,如果是过期数据(窗口代表的时间距离当前已经超过 1 分钟),需要先重置这个窗口实例的数据。


统计数据同理,如统计过去一分钟的 QPS 数据,就是将每个窗口的值相加,当中需要判断窗口数据是否是过期数据,即判断窗口的 WindowWrap 实例是否是一分钟内的数据。


核心逻辑都封装在了 currentWindow(long timeMillis) 和 values(long timeMillis)方法中。


添加数据的时候,我们要先获取操作的目标窗口,也就是


分维度数据统计


currentWindow


Sentinel 在这里处理初始化和过期重置的情况

6.png

获取数据,使用的是

values

返回“有效”窗口中的数据

image.png

isWindowDeprecated

image.png

案例

image.png

红色部分的Context 代表一个调用链的入口,Context 实例设置在 ThreadLocal,所以它是跟着线程走的,如果要切换线程,需要手动切换。

ContextUtil#enter 有俩参数:

context name

调用链的入口,以区分不同调用链路,默认是

image.png

origin

调用方标识,作用


黑白名单的授权控制


统计诸如从应用 application-a 发起的对当前应用 interfaceXxx() 接口的调用,目前这个数据会被统计,但是 dashboard 中并不展示


进入 BlockException 异常分支,代表该次请求被流量控制规则限制,一般会让代码走入到熔断降级逻辑。当然,BlockException 其实有好多个子类

image.png

亦可 catch 具体子类处理。

SphU#entry 方法的参数:

  • 第一个参数
    标识资源,通常就是我们的接口标识,对于数据统计、规则控制等,我们一般都是在这个粒度上进行的,根据这个字符串来唯一标识,它会被包装成 ResourceWrapper 实例。
  • 第二个参数
    标识资源的类型
  • image.png
  • EntryType.IN

入口流量,比如我们的接口对外提供服务,那通常就是控制入口流量

EntryType.OUT

image.png

默认就是出口流量,它的业务需要调用订单服务,像这种情况,压力其实都在订单服务,那就指定它为出口流量。


流量类型在 SystemSlot 类中用以实现自适应限流,根据系统健康状态来判断是否要限流,如果是 OUT 类型,由于压力在外部系统中,所以就不需要执行该规则。


若在一个方法中写,要注意内层的 Entry 先 exit,才能做外层的 exit,否则会抛出异常。源码角度来看,是在 Context 实例中,保存了当前的 Entry 实例。


源码解析


ContextUtil


static 代码块

这里会添加一个默认的 EntranceNode 实例。

image.png

enter

该行代码可不写,通常情况下,都不会显示设置 context。

ContextUtil.enter("user-center", "app-A");

如果不显式调用该方法,就会进入到默认 context。

image.png

然后上面的这个方法会走进 ContextUtil#trueEnter,添加名为 “user-center” 的 EntranceNode 节点:

image.png

若不显式调用 ContextUtil#enter,那 root 就只有一个默认节点 sentinel_default_context。


context,线程执行的上下文,在 Sentinel 中对于一个新的 context name,Sentinel 会往树中添加一个 EntranceNode 实例。所以它的作用是为了区分调用链路,标识调用入口。在 sentinel-dashboard 中,我们可以很直观地看出调用链路:

image.png

SphU

entry

CtSph#entryWithPriority

image.png

lookProcessChain(resourceWrapper)

链中每一个节点是一个 Slot 实例,这个链通过 BlockException 异常来告知调用入口最终的执行情况。


Sentinel 提供了 SPI 端点,让我们可以自己定制 Builder,如添加一个 Slot 进去。


由于 SlotChainBuilder 接口设计,我们只能全局所有的 resource 使用相同的责任链配置。

image.png

按照默认的 DefaultSlotChainBuilder 生成的责任链继续源码。

对相同的 resource,使用同一责任链实例,不同 resource,使用不同责任链实例。

resource 实例根据 resource name 来判断,和线程没有关系。


参考

https://juejin.cn/post/6906302891875647495

https://github.com/alibaba/Sentinel/wiki/Sentinel-%E6%A0%B8%E5%BF%83%E7%B1%BB%E8%A7%A3%E6%9E%90

https://www.javadoop.com/post/sentinel


目录
相关文章
|
存储 NoSQL 调度
【Redis源码】集群之哨兵sentinel故障转移 (十二)
【Redis源码】集群之哨兵sentinel故障转移 (十二)
161 0
|
存储 NoSQL Redis
【Redis源码】集群之哨兵sentinel初识(十一)
【Redis源码】集群之哨兵sentinel初识(十一)
90 0
|
Java 测试技术 Nacos
Sentinel源码改造,实现Nacos双向通信!
Sentinel源码改造,实现Nacos双向通信!
221 0
Sentinel源码改造,实现Nacos双向通信!
|
存储 SpringCloudAlibaba 监控
系统高可用番外篇:浅析sentinel源码
Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从**限流、流量整形、熔断降级、系统负载保护、热点防护**等多个维度来帮助开发者保障微服务的稳定性。
155 0
系统高可用番外篇:浅析sentinel源码
|
JSON 监控 安全
Spring Cloud Gateway 整合阿里 Sentinel网关限流实战!
Spring Cloud Gateway 整合阿里 Sentinel网关限流实战!
|
JSON 监控 算法
阿里限流神器Sentinel夺命连环 17 问?
阿里限流神器Sentinel夺命连环 17 问?
|
存储 监控 算法
Sentinel源码剖析之核心组件作用和介绍
Sentinel 是分布式系统的防御系统。以流量为切入点,通过动态设置的流量控制、服务熔断降级、系统负载保护等多个维度保护服务的稳定性,通过服务降级增强服务被拒后用户的体验。
138 0
|
Java API 调度
Sentinel源码剖析之初始化
用过sentinel的都知道SphU是一切的源头 entry = SphU.entry(target, EntryType.IN); 通过这行代码来获取访问令牌,如果获取到令牌,那么就可以访问目标资源,没有获取到entry便无法访问对应资源。
490 0
|
存储 SQL 算法
Sentinel源码剖析之执行流程
Sentinel主要用来流控,熔断降级保护目标资源用的,常用集成SCG,SpringBoot,SprinMVC这些,但底层本质没变,但是体现形式上会有差别。例如SCG底层是Netty 和 SpringWebFlux 采用Reactor Stream处理,SpringBoot内部通过AOP处理流控这些。
420 0
|
算法 BI Sentinel
Sentinel核心源码解析二
Sentinel核心源码解析二 二、Sentinel核心源码解析 三、滑动时间窗算法 对于滑动时间窗算法的源码解析分为两部分:对数据的统计,与对统计数据的使用。不过,在分析源码之前,需要先理解该算法原
149 0
下一篇
无影云桌面