Sentinel的核心原理,也就是前面提到暗流涌动的SphU.entry(…)这行代码背后的逻辑。
Sentinel会为每个资源创建一个处理链条,就是一个责任链,第一次访问这个资源的时候创建,之后就一直复用,所以这个处理链条每个资源有且只有一个。
SphU.entry(…)这行代码背后就会调用责任链来完成对资源的检查逻辑。
这个责任链条中每个处理节点被称为ProcessorSlot,中文意思就是处理器槽
这个ProcessorSlot有很多实现,但是Sentinel的核心就下面这8个:
这些实现会通过SPI机制加载,然后按照一定的顺序组成一个责任链。
默认情况下,节点是按照如下的顺序进行排序的
虽然默认就8个,但是如果你想扩展,只要实现ProcessorSlot,按照SPI的规定配置一下就行。
下面就来按照上面节点的处理顺序来好好扒一扒这8个ProcessorSlot。
这个节点的作用是来设置当前资源对应的入口 的统计Node 。
首先什么是统计Node?
比如就拿上面的例子来说,当/sayHello这个资源的qps超过2的时候,要触发限流。
但是有个疑问,Sentinel是怎么知道/sayHello这个资源的qps是否达到2呢?
当然是需要进行数据统计的,只有通过统计,才知道qps是否达到2,这个进行数据统计的类在Sentinel中叫做Node。
通过Node这个统计的类就知道有多少请求,成功多少个,失败多少个,qps是多少之类的。底层其实是使用到了滑动窗口算法。
那么什么叫对应的入口?
在Sentinel中,支持同一个资源有不同的访问入口。
只不过一般一个资源就一个入口,比如一个http接口一般只能通过http访问,但是Sentinel支持多入口,你可以不用,但是Sentinel有。
所以NodeSelectorSlot的作用就是选择资源在当前调用入口的统计Node,这样就实现了统计同一个资源在不同入口访问数据。
资源的入口可以在进入资源之前通过ContextUtil.enter(“入口名”, origin)来指定,如果不指定,那么入口名称默认就是sentinel_default_context。
在SpringMVC环境底下,所有的http接口资源,默认的入口都是sentinel_spring_web_context
入口名称也可以通过控制台看到
ClusterBuilderSlot的作用跟NodeSelectorSlot其实是差不多的,也是用来选择统计Node,但是选择的Node的统计维护跟NodeSelectorSlot不一样。
ClusterBuilderSlot会选择两个统计Node:
资源调用者很好理解,比如一个http接口资源肯定会被调用,那么调用这个接口的服务或者应用其实就是资源的调用者,但是一般资源的调用者就是指某个服务,后面调用者我可能会以服务来代替。
一个接口可以被很多服务调用,所以一个资源可以很多调用者,而不同调用者都会有单独的一个统计Node,用来分别统计不同调用者对资源的访问数据。
那么如何知道访问资源来自哪个服务(调用者)呢?
也是通过ContextUtil.enter(“入口名”, origin)来指定,这个方法的第二个参数origin就是代表服务名的意思,默认是空。
所以ContextUtil.enter(…)可以同时指定资源的入口和调用者,一个资源一定有入口,因为不指定入口默认就是sentinel_default_context,但是调用者不指定就会没有。
对于一个http请求来说,Sentinel默认服务名需要放到S-user这个请求头中,所以如果你想知道接口的调用服务,需要在调用方发送请求的时候将服务名设置到S-user请求头中。
当资源所在的服务接收到请求时,Sentinel就会从S-user请求头获取到服务名,之后再通过ContextUtil.enter(“入口名”, “调用者名”)来设置当前资源的调用者
所以这一节加上上一节,我们知道了一个资源其实有三种维度的统计Node:
为了方便区分,我来给这三个统计Node取个响亮的名字
不同入口的访问数据就叫他DefaultNode,统计所有入口访问数据之和就叫他ClusterNode,来自某个服务的访问数据就叫他OriginNode。
这个Slot没什么好说的,通过名字可以看出来,其实就是用来打印日志的。
当发生异常,就会打印日志。
这个Slot就比较重要了,就是用来统计数据的。
前面说的NodeSelectorSlot和ClusterBuilderSlot,他们的作用就是根据资源当前的入口和调用来源来选择对应的统计Node。
而StatisticSlot就是对这些统计Node进行实际的统计,比如加一下资源的访问线程数,资源的请求数量,系统的入口qps,线程数,平均响应时间这些指标等等。
至于cpu使用率、负载指标,Sentinel会启动一个定时任务,每隔1s会去读取一次当前系统的cpu和负载。
Authority是授权的意思,这个Slot的作用是对资源调用者进行授权,就是黑白名单控制。
可以通过控制台来添加授权规则。
在AuthoritySlot中会去获取资源的调用者,之后会跟授权规则中的资源应用这个选项进行匹配,之后就会出现有以下2种情况:
这个的作用是根据整个系统运行的统计数据来限流的,防止当前系统负载过高。
它支持入口qps、线程数、响应时间、cpu使用率、负载5个限流的维度。
这个Slot会根据预设的规则,结合前面的统计出来的实时信息进行流量控制。
这里我们来好好扒一扒这些配置项的意思。
这个配置就比较有意思了,分为直接、关联、链路三种模式:
到这,其实前面说到的一个资源的三种统计维度的数据都用到了,现在应该明白了为什么需要这么多维度的数据,就是为不同维度限流准备的。
这个就是如果是通过qps来限流,并且达到了限流的条件之后会做什么,如果是线程数,就直接抛出BlockException异常
也有三种方式,快速失败、Warm Up、排队等待
这是整个责任链中最后一个slot,这个slot的作用是用来熔断降级的。
Sentinel支持三种熔断策略:慢调用比例、异常比例 、异常数,通过规则配置也可以看出来。
熔断器的工作流程大致如下
Sentinel会为每个设置的规则都创建一个熔断器,熔断器有三种状态,OPEN(打开)、HALF_OPEN(半开)、CLOSED(关闭)
一般来说,熔断降级其实是对于服务的调用方来说的。
在项目中会经常调用其它服务或者是第三方接口,而对于这些接口,一旦它们出现不稳定,就有可能导致自身服务长时间等待,从而出现响应延迟等等问题。
此时服务调用方就可基于熔断降级方式解决。
一旦第三方接口响应时间过长,那么就可以使用慢调用比例规则,当出现大量长时间响应的情况,那么就直接熔断,不去请求。
虽然说熔断降级是针对服务的调用方来说,但是Sentinel本身并没有限制熔断降级一定是调用其它的服务。