Sentinel主要功能
Sentinel 是阿里巴巴开源的一款流量控制、熔断降级组件,它主要用于保护微服务系统。Sentinel 的主要功能包括以下几个方面:
1. 流量控制(Flow Control):
Sentinel 通过控制并发请求的数量或速率,来保护服务的稳定性和可用性。
支持 QPS(每秒查询率)模式和并发线程数模式,可以灵活地控制不同粒度的流量。
提供了多种流量整形策略,如直接拒绝、排队等待、预热模式等。
2. 熔断降级(Circuit Breaker):
当下游服务出现异常或响应时间过长时,Sentinel 可以自动熔断,停止调用下游服务,避免故障传播和系统崩溃。
支持多种熔断策略,如基于慢调用比例、异常比例或异常数进行熔断。
熔断状态可以在一段时间后自动或半自动恢复,以测试下游服务是否已恢复正常。
3. 系统自适应保护(System Adaptive Protection):
Sentinel 可以根据系统的实时负载情况,自动调整流量控制规则,防止系统过载。
通过实时统计系统的 QPS、响应时间等指标,自动触发降级或限流策略,保证系统的稳定运行。
4. 热点参数限流(Hotspot Parameter Flow Control):
Sentinel 可以对热点参数进行限流,防止某个热点参数被过度请求,导致系统资源耗尽。
支持对参数进行精确匹配或模糊匹配,以及自定义热点参数规则。
5. 资源隔离(Resource Isolation):
Sentinel 支持对不同的服务或资源进行隔离,防止一个服务的故障影响其他服务。
通过线程池隔离、信号量隔离等方式,实现对不同资源的独立管理和控制。
6. 实时监控和告警(Real-time Monitoring and Alerting):
Sentinel 提供了丰富的监控和告警功能,可以实时查看系统的运行状况、流量数据、熔断状态等。
支持多种告警方式,如邮件、短信、钉钉等,帮助开发人员及时发现和解决问题。
7. 扩展性(Extensibility):
Sentinel 支持自定义规则、扩展数据源、扩展流控处理器等功能,满足各种复杂的业务需求。
提供了丰富的 SPI(Service Provider Interface)接口,方便用户进行自定义扩展。
8. 与 Spring Cloud、Dubbo 等框架的集成:
Sentinel 提供了与 Spring Cloud、Dubbo 等微服务框架的集成方案,方便用户在微服务系统中使用 Sentinel 进行流量控制和熔断降级。
Sentinel基本组件:
1. 核心库(Java 客户端) :这是Sentinel的核心部分,它不依赖任何框架/库,能够运行于Java 7及以上的版本的运行时环境。同时,它对Dubbo、Spring Cloud等框架也有较好的支持。这个库提供了实时的流量控制、熔断降级、系统负载保护等功能,是微服务架构中不可或缺的一环。
2. 控制台(Dashboard):这是Sentinel的管理工具,主要负责管理推送规则、监控、集群限流分配管理、机器发现等。通过控制台,用户可以直观地查看和管理Sentinel的各种规则和限制。
基本控制组件主要包括以下几个部分:
1. 流量控制组件:
Sentinel 的核心功能之一,用于控制进入系统的流量,防止系统过载。它可以根据系统的处理能力,对流量进行限制和调整,确保系统的稳定性和可用性。
支持多种流量控制策略,如直接拒绝、排队等待、预热模式等,可以根据不同的业务场景选择合适的策略。
2. 熔断降级组件:
当下游服务出现故障或响应时间过长时,Sentinel 可以自动熔断,停止调用下游服务,避免故障传播和系统崩溃。
熔断降级组件可以根据预设的熔断策略(如慢调用比例、异常比例或异常数)进行熔断,并在一段时间后自动或半自动恢复,以测试下游服务是否已恢复正常。
3. 系统自适应保护组件:
Sentinel 可以根据系统的实时负载情况,自动调整流量控制规则,防止系统过载。
该组件通过实时统计系统的 QPS、响应时间等指标,自动触发降级或限流策略,确保系统的稳定运行。
4. 规则管理器:
Sentinel 的规则管理器用于定义和管理各种控制规则,如流量控制规则、熔断降级规则等。
用户可以通过 Sentinel 的控制台或 API 接口来配置和管理这些规则,实现对系统行为的精确控制。
5. 监控和告警组件:
Sentinel 提供了丰富的监控和告警功能,可以实时查看系统的运行状况、流量数据、熔断状态等。
该组件支持多种告警方式,如邮件、短信、钉钉等,帮助开发人员及时发现和解决问题。
6. 数据源组件:
Sentinel 支持多种数据源,用于存储和获取控制规则。
数据源可以是本地文件、数据库、远程配置中心等,用户可以根据实际需求选择合适的数据源。
流量治理核心步骤:
1. 定义资源和规则:
使用 @SentinelResource 注解来定义受 Sentinel 保护的资源。这些资源可以是方法、接口或者其他需要被流量治理的对象。
通过 Sentinel 的控制台或 API 接口来配置和管理流量控制规则、熔断降级规则等。这些规则定义了流量治理的行为和策略。
2. 流量控制:
根据预设的流量控制规则,对进入系统的流量进行限制和调整。这可以基于 QPS(每秒查询率)、并发线程数等指标进行。
Sentinel 支持多种流量控制策略,如直接拒绝、排队等待、预热模式等。可以根据不同的业务场景选择合适的策略。
3. 熔断降级:
当下游服务出现故障或响应时间过长时,Sentinel 可以自动熔断,停止调用下游服务,避免故障传播和系统崩溃。
熔断降级组件可以根据预设的熔断策略(如慢调用比例、异常比例或异常数)进行熔断,并在一段时间后自动或半自动恢复,以测试下游服务是否已恢复正常。
4. 实时监控和告警:
Sentinel 提供了丰富的监控和告警功能,可以实时查看系统的运行状况、流量数据、熔断状态等。
通过实时监控,开发人员可以及时发现潜在问题并进行处理。告警功能则可以在系统出现问题时及时通知相关人员,以便及时处理。
5. 系统自适应保护:
Sentinel 可以根据系统的实时负载情况,自动调整流量控制规则,防止系统过载。
这可以通过实时统计系统的 QPS、响应时间等指标来实现,自动触发降级或限流策略,确保系统的稳定运行。
6. 规则动态更新:
Sentinel 支持规则的动态更新,这意味着可以在运行时修改和更新流量控制规则和熔断降级规则。
这使得开发人员能够根据实际情况灵活地调整系统的流量治理策略,以满足业务需求的变化。
通过以上核心步骤,Sentinel 能够在分布式服务架构中提供有效的流量治理功能,保障微服务的稳定性和可用性。
两个核心架构
Sentinel的源码层面的两个核心架构确实包括责任链模式架构和滑动窗口数据统计架构,下面分别解释:
1. 责任链模式架构(Slot Chain):
-
Sentinel使用责任链模式(Chain of Responsibility Pattern)来组织不同的处理逻辑。在Sentinel中,这个责任链被称为Slot Chain。
-
每个Slot在链中负责执行一种特定的逻辑,如流量控制、熔断降级、系统保护等。当流量进入时,它会按照Slot Chain中定义的顺序逐个执行每个Slot的逻辑。
-
Sentinel通过SlotChainBuilder来对责任链的整个链路进行初始化,并使用SPI(Service Provider Interface)和ServiceLoader来进行Slot的定义和加载。
-
这种架构使得Sentinel可以灵活地添加、删除或修改处理逻辑,提高了系统的可扩展性和可维护性。
2. 滑动窗口数据统计架构:
-
Sentinel使用滑动窗口来统计各种指标数据,如QPS、响应时间、异常数量等。这些数据被用于后续的限流、熔断等决策。
-
滑动窗口是一种数据结构,它可以在固定时间窗口内滑动,以收集和更新统计数据。这种方式可以有效地处理实时数据,同时避免了全局窗口的统计误差。
-
Sentinel的滑动窗口实现主要包括几个核心类:LeapArray(滑动窗口顶层数据结构)、WindowWrap(每个滑动窗口的包装类)、MetricBucket(指标桶,存储具体的统计数据)和ArrayMetric(滑动窗口的入口类,实现了Metric指标收集核心接口)。
-
当有新的请求进入时,Sentinel会根据当前时间找到对应的滑动窗口,并更新该窗口中的统计数据。这些数据随后被用于判断是否需要执行限流、熔断等策略。
这两个核心架构共同构成了Sentinel的核心功能,使得Sentinel能够在分布式系统中提供有效的流量控制和熔断降级能力。
滑动窗口的核心数据结构
Sentinel的滑动窗口算法中,核心数据结构主要包括LeapArray、WindowWrap、MetricBucket。以下是这些数据结构在Sentinel滑动窗口算法中的作用:
ArrayMetric
滑动窗口核心实现类,实现了指标收集核心接口,该接口主要定义一个滑动窗口中的指标数据,包含了成功数量、异常数量、阻塞数量、TPS、响应时间等数据。
java
*/
public class ArrayMetric implements Metric {
private final LeapArray<MetricBucket> data;
public ArrayMetric(int sampleCount, int intervalInMs) {
this.data = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
}
public ArrayMetric(int sampleCount, int intervalInMs, boolean enableOccupy) {
if (enableOccupy) {
this.data = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
} else {
this.data = new BucketLeapArray(sampleCount, intervalInMs);
}
}
./....
}
- sampleCount 采集间隔抽取数量,默认2。
- intervalInMs 采集时间间隔,即滑动窗口总时间。
- enableOccupy 是否允许抢占,即当前时间戳已经达到限制后,是否可以占用下一个时间窗口容量。
LeapArray
这是Sentinel滑动时间窗口算法的顶层数据结构,用于管理整个滑动窗口的划分和更新。
java
public abstract class LeapArray<T> {
protected int windowLengthInMs;
protected int sampleCount;
protected int intervalInMs;
private double intervalInSecond;
protected final AtomicReferenceArray<WindowWrap<T>> array;
/**
* The conditional (predicate) update lock is used only when current bucket is deprecated.
*/
private final ReentrantLock updateLock = new ReentrantLock();
...
}
windowLengthInMs: 每一个窗口的时间间隔。
sampleCount:抽样个数,统计时间间隔中包含的滑动窗口个数
intervalInMs 统计时间间隔毫秒
intervalInSecond 时间间隔秒
AtomicReferenceArray<WindowWrap> array 滑动窗口的数组
WindowWrap
这个数据结构用于包装每个时间窗口,并存储该时间窗口内的统计数据,如请求计数等。
java
public class WindowWrap<T> {
/**
* Time length of a single window bucket in milliseconds.
*/
private final long windowLengthInMs;
/**
* Start timestamp of the window in milliseconds.
*/
private long windowStart;
/**
* Statistic data.
*/
private T value;
......
}
windowLengthInMs:单个窗口时间长度
windowStart:窗口开始时间
value: 统计数据
- WindowWrap 用于包装 Bucket,并和 Bucket 一起创建。
- WindowWrap 数组实现滑动窗口,Bucket 负责统计各项指标数据,WindowWrap 用于记录 Bucket 时间窗口信息。
- 定位 Bucket 实际上是定位 WindowWrap,获取到 WindowWrap 就能得到 Bucket。
MetricBucket
这是每个时间窗口内部的具体指标桶,用于记录在当前时间窗口内的请求数量或其他相关统计数据,指标数据包括请求总数、成功总数、异常总数、总耗时、最小耗时、最大耗时等,而一个 Bucket 可以是记录一秒内的数据,也可以是 10 毫秒内的数据,这个时间长度称为窗口时间。
java
public class MetricBucket {
private final LongAdder[] counters;
private volatile long minRt;
....
}
MetricBucket 巧妙地利用了一个 LongAdder 数组来追踪并记录一段时间内的各项关键指标数据。每个 LongAdder 元素专注于一种 MetricEvent,分别用于计量时间窗口内的请求总数、异常发生次数以及总耗时。LongAdder 的设计确保了数据更新的原子性,并在高并发场景下提供了比 AtomicLong 更出色的性能表现,从而确保了数据的一致性和准确性。
java
public enum MetricEvent {
/**
* Normal pass.
*/
PASS,
/**
* Normal block.
*/
BLOCK,
EXCEPTION,
SUCCESS,
RT,
/**
* Passed in future quota (pre-occupied, since 1.5.0).
*/
OCCUPIED_PASS
}
Bucket 记录总的成功请求数或者异常总数、总的请求处理耗时,根据事件类型 (MetricEvent) 从 Bucket 的 LongAdder 数组中获取对应的 LongAdder。
Bucket 记录一个成功请求或者一个异常请求、处理请求的耗时,可根据事件类型(MetricEvent)从 LongAdder 数组中获取对应的 LongAdder,并调用其 add 方法。
MetricEvent
指标类型,例如通过数量、阻塞数量、异常数量、成功数量、响应时间等。
java
public enum MetricEvent {
/**
* Normal pass.
*/
PASS,
/**
* Normal block.
*/
BLOCK,
EXCEPTION,
SUCCESS,
RT,
/**
* Passed in future quota (pre-occupied, since 1.5.0).
*/
OCCUPIED_PASS
}
Sentinel通过这些数据结构实现了对滑动时间窗口的高效管理,能够精确地控制每个时间窗口内的请求数量,并根据这些数据进行流量控制和熔断降级等操作。这种设计使得Sentinel能够平滑地处理流量的突增情况,并防止因瞬间大量请求而导致的限流误判。
责任链模式
责任链模式是一种行为型设计模式,他通过将一系列的操作行为串联成一个链路构造出一个链式的结构,每一次调用链路的时候,链路上的每一个行为都可能会对此次调用进行一定的处理。责任链模式可以用于权限控制,OA流程等等,当然在Java Web中的Filter也使用到了这种设计模式。
ProcessorSlot
Sentinel定义了一个接口ProcessorSlot,这个接口就是责任链模式的实现核心。
java
public interface ProcessorSlot<T> {
void entry(Context context, ResourceWrapper resourceWrapper, T param, int count, boolean prioritized,
Object... args) throws Throwable;
void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized,
Object... args) throws Throwable;
void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
}
接口中定义了四个方法:
- entry 进入Slot
- fireEntry entry执行完成后调用
- exit 离开Slot
- fireExit exit执行完成后调用
ProcessorSlot定义了抽象实现类AbstractLinkedProcessorSlot,FlowSlot,DegradeSlot等等实现都继承了这个抽象类来实现,Slot就是整个责任链的链路。
Sentinel通过SlotChainBuilder来对责任链的整个链路进行初始化。在默认实现中各个Slot使用Spi的形式进行定义和管理,并且在此处使用ServiceLoader来进行装载。在此时决定了整个链路的执行顺序和优先级。后续的流量进入之后就会按照预定的顺序执行每个Slot的方法。
Sentinel定义了SphU,SphO等类来实现流量的入口管控,流量进入到整个链路中执行整个责任链。