Sentinel组件学习
- 1. Sentinel是什么
- 2. Sentinel的作用
- 3. 为啥使用Sentinel
- 4. SpringCloud整合Sentinel代码示例
- 4.1. 搭建Sentinel Dashboard
- 4.2. SpringCloud项目接入Sentinel
- 4.3. 使用@SentinelResource注解
- 5. Sentinel Dashboard使用
- 5.1 流控规则
- 流控模式
- 流控效果
- 5.2 熔断规则
- 熔断策略
- 5.3 热点规则
- 5.4 授权规则
- 5.5. 自定义异常处理
- 5.6 openFegin使用Sentinel
1. Sentinel是什么
Sentinel是阿里巴巴开源的一款面向分布式系统的实时监控和自动化故障恢复工具。它主要用于流量控制、熔断降级和系统负载保护,旨在帮助开发者有效地保护应用程序,防止故障和异常情况的发生。Sentinel不仅支持Java语言,还提供了Go、C++等多语言的原生实现,广泛应用于微服务架构中。
常见的容错解决方案
方案名 | 描述 |
---|---|
隔离 | 将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时, 能将问题和影响隔离在某个模块内部,不波及其它模块。常见的隔离方式有:线程池隔离和信号量隔离. |
超时 | 在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应,就断 开请求,释放掉线程。 |
限流 | 限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到的需要 限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。 |
熔断 | 在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性, 可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。 |
降级 | 降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。 |
2. Sentinel的作用
Sentinel提供了以下几个核心功能:
- 实时监控:Sentinel可以监控分布式系统中的各种指标,如QPS(每秒查询率)、CPU、内存等,并提供实时的监控数据和报警功能。
- 流量控制:根据系统的负载情况动态调整流量,以保证系统的稳定性和可靠性。
- 熔断降级:当系统负载过高或某个服务出现故障时,Sentinel可以自动熔断降级,减少对整体系统的影响。
- 系统负载保护:通过多种手段保护系统不被过载请求压垮。
- 热点流量防护:对热点参数进行流量控制,防止流量突增导致的系统崩溃。
3. 为啥使用Sentinel
相较于传统的熔断降级工具如Hystrix,Sentinel具有以下优势:
- 更广泛的应用场景:Sentinel不仅适用于Spring Cloud,还适用于Dubbo、gRPC、Servlet等多种应用场景。
- 更丰富的功能:Sentinel除了熔断降级、流量控制外,还提供了系统保护、热点流量防护、授权等多种功能。
- 灵活的规则配置:Sentinel提供了丰富的规则配置功能,支持动态调整,易于管理和维护。
- 高效的性能:Sentinel采用了高效稳定的设计和实现,可以在大规模分布式系统中运行良好。
- 开源免费和社区支持:Sentinel是一款开源软件,可以免费使用和修改,并且拥有一个活跃的开源社区,开发者可以获得持续的支持和帮助。
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 线程池隔离/信号量隔离 | 信号量隔离 (并发线程数限流) | 信号量隔离 |
熔断降级 | 基于异常比率、响应时间 | 基于异常比率 | 基于异常比率、异常数 |
实时统计 | 滑动窗口 (LeapArray) | 滑动窗口 (基于 RxJava) | Ring Bit Buffer |
动态规限 | 支持多种数据源 | 有限支持 | 支持多种数据源类型 |
扩展性 | 多个扩展点,插件的形式 | 接口的形式 | 基于注解的支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式、匀速器模式、预热排队 | 简单的 Rate Limiter | 不支持 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现 | 简单的监控查看 | 不提供控制台,可对接其他监控系统 |
4. SpringCloud整合Sentinel代码示例
4.1. 搭建Sentinel Dashboard
首先,需要下载Sentinel Dashboard的jar包,并启动Dashboard服务。
sentinel 提供一个轻量级的控制台, 它提供机器发现、单机资源实时监控以及规则管理等功能。
1 下载jar包,解压到文件夹
https://github.com/alibaba/Sentinel/releases
2 启动控制台
# 下载Sentinel Dashboard jar包
# 启动Dashboard服务 (这里使用静默启动)
nohup java -Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=sentinel-dashboard -jar /home/sentinel-dashboard-1.8.8.jar >nohuout &
3 访问请求
启动后,你可以在浏览器中通过访问 http://localhost:8081
(或者你指定的端口)来访问 Sentinel Dashboard。默认的用户名和密码都是 sentinel
。
4.2. SpringCloud项目接入Sentinel
在SpringCloud项目中引入Sentinel的依赖,并配置Dashboard地址。
pom.xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
application.yml
spring:
cloud:
sentinel:
transport:
# 项目使用该端口与Sentinel dashboard应用进行数据交互
port: 8719
# Sentinel dashboard应用访问地址
dashboard: localhost:8080
4.3. 使用@SentinelResource注解
在需要保护的方法上使用@SentinelResource
注解,并指定资源名称和限流规则。
@Service
public class UserServiceImpl implements UserService {
@Override
@SentinelResource(value="getUserById",blockHandler="限流方法",fallback="熔断方法")
public User getUserById(Long id) {
return userDao.selectById(id);
}
}
属性名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
value/name | String | 是 | 资源名称,用于在 Sentinel 控制台中标识和配置该资源。 |
blockHandler | String | 否 | 对应的 block 异常处理函数名称。当资源被限流、降级或系统保护时,会调用此函数。 |
blockHandlerClass | Class<?> | 否 | 当 blockHandler 函数位于其他类时,需要指定该类。注意,对应的函数必须是 static 的。 |
fallback | String | 否 | 对应的 fallback 函数名称。当资源调用失败(如超时、异常等)时,会调用此函数进行回退处理。 |
fallbackClass | Class<?> | 否 | 当 fallback 函数位于其他类时,需要指定该类。注意,对应的函数必须是 static 的。 |
defaultFallback | String | 否(自1.6.0起) | 默认的 fallback 函数名称,用于通用的 fallback 逻辑。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。 |
entryType | EntryType | 否 | 资源的 entry 类型,默认为 EntryType.OUT,表示出站资源。还可以设置为 EntryType.IN 表示入站资源(如 Web 请求)。 |
exceptionsToIgnore | Class<? extends Throwable>[] | 否(自1.6.0起) | 指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。 |
5. Sentinel Dashboard使用
我们可以在Sentinel Dashboard中配置流控规则(限流策略)、熔断规则(熔断策略)、热点规则(热点数据限流规则)。配置成功启动项目,随便访问一个接口,看控制台效果:。数据基于默认内存存储,被监控项目重启监控数据会被清掉(可以修改为ZooKeeper、redis、nacos、apollo)
5.1 流控规则
字段名 | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值,即允许的请求数量或线程数 | |
grade | 限流阈值类型,可以是QPS或线程数模式 | QPS 模式, 示例:单机阈值为1时候,如果每秒请求数量大于1则会触发限流规则 并发线程数,示例:单机阈值为1,如果并发请求超过1则会触发限流规则 |
limitApp | 流控针对的调用来源,用于区分不同应用 | default,代表不区分调用来源 |
strategy | 调用关系限流策略:直接、链路、关联 | 根据具体实现和版本可能有所不同,这里不提供默认值 |
controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流 | 直接拒绝 |
流控模式
- 直接模式
- 定义:直接模式是最基本的流控模式,它直接针对当前资源进行流量控制,通过设置QPS(每秒查询率)或并发线程数等阈值来限制资源的访问。
- 特点:适用于需要对单个资源进行严格控制的场景,如API接口、微服务等。
- 应用:在直接模式下,当资源的实际流量超过配置的阈值时,Sentinel将拒绝或降级该资源的访问请求,以保护系统不受过大流量的冲击。
- 关联模式
- 定义:关联模式是一种更为灵活的流控方式,它允许将多个相关的资源进行关联,并在整体上进行流量控制。
- 特点:通过定义资源之间的关联关系,当某个资源的访问达到一定限制时,会触发关联的其他资源的流控,以适应多资源之间的复杂交互。
- 应用:例如,在电商系统中,当订单支付接口的访问量达到阈值时,可以关联限制商品查询接口的访问,以防止系统因资源分配不均而崩溃。
- 链路模式
- 定义:链路模式主要适用于微服务架构中的流量控制,它基于整个调用链路进行流量控制,确保整个系统的稳定性。
- 特点:链路模式可以识别并控制整个请求链路中的流量,从而有效地应对分布式系统中可能出现的问题。
- 应用:在微服务架构中,不同服务之间的调用关系复杂,链路模式可以确保在整个调用链路中,资源的访问不会超过预设的阈值,从而保护系统的稳定性。
流控效果
- 快速失败
- 定义:当流量超过设定的阈值时,新的请求会被立即拒绝,并抛出异常(如FlowException)。
- 特点:这是一种简单的流控效果,能够快速响应流量激增的情况,避免系统过载。
- 应用:适用于对系统稳定性要求较高的场景,如核心接口、高频接口等。
- 预热模式(Warm Up)
- 定义:预热模式是一种更为平滑的流控效果,它允许系统在启动时或流量突然增大时,逐渐放宽限流策略,使系统从空闲状态过渡到繁忙状态。
- 特点:通过设置一个预热时长和冷却因子,系统在预热期内逐渐提高流量阈值,从而避免系统在短时间内因流量激增而崩溃。
- 应用:适用于系统启动初期或需要应对突发流量的场景,如秒杀系统、抢购活动等。
- 排队等待
- 定义:排队等待模式允许所有请求按照先后次序排队执行,但两个请求的间隔不能小于指定时长。
- 特点:这种流控效果可以在一定程度上缓解流量峰值对系统的冲击,但也可能导致请求响应时间延长。
- 应用:适用于对系统响应时间有一定容忍度的场景,如非实时性业务、后台任务等。
5.2 熔断规则
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即规则的作用对象 | - |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | - |
timeWindow | 熔断时长,单位为秒(s) | - |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为毫秒ms),如60*1000代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) | - |
熔断策略
- 慢调用比例 (SLOW_REQUEST_RATIO)
- 说明:当资源的响应时间超过设定的阈值时,将其视为慢调用。如果慢调用的比例超过设定的阈值,则触发熔断。
- 重要属性:
count
:慢调用临界RT(即响应时间阈值),超出此值的调用被统计为慢调用。timeWindow
:统计时间窗口,单位为秒,用于计算慢调用比例。
- 异常比例 (ERROR_RATIO)
- 说明:当资源调用出现异常的比例超过设定的阈值时,触发熔断。
- 重要属性:
count
:异常比例阈值,范围是[0.0, 1.0],代表0%到100%的异常比例。timeWindow
:统计时间窗口,单位为秒,用于计算异常比例。
- 异常数 (ERROR_COUNT)
- 说明:当资源调用在统计时间窗口内的异常数超过设定的阈值时,触发熔断。
- 重要属性:
count
:异常数阈值,即统计时间窗口内允许的最大异常数。timeWindow
:统计时间窗口,单位为秒。
每种熔断策略都允许设置timeWindow
来定义统计时间窗口,以及触发熔断的阈值(如慢调用RT、异常比例或异常数)。Sentinel通过这些策略来保护系统,避免因为不稳定的服务或资源而导致整个系统的崩溃。
5.3 热点规则
Sentinel的热点规则(ParamFlowRule)用于控制对包含热点参数的资源调用的流量。热点参数规则可以针对包含特定参数的请求进行流量控制,以防止某个热点参数导致的流量过载。
以下是热点规则(ParamFlowRule)相关属性的列表及其说明:
属性名 | 类型 | 说明 |
---|---|---|
resource | String | 资源名,必填项,用于标识受保护的热点资源。 |
grade | int | 限流模式。目前Sentinel热点参数限流支持QPS模式(0)。 |
count | double | 限流阈值,针对参数索引的单个统计周期(如秒)内的请求数阈值。 |
durationInSec | int | 统计时间窗口,单位为秒,默认是1秒。 |
controlBehavior | int | 流控效果,支持快速失败(0,默认)和匀速排队(1)。 |
paramIdx | int | 热点参数的索引,在请求的参数列表中,从0开始计数。 |
paramFlowItemList | List | 热点参数规则的详细列表,可以针对多个参数分别设置限流规则。 |
5.4 授权规则
基于调用方身份的黑白名单控制,以确保只有特定的调用方能够访问敏感资源。以下是授权规则(AuthorityRule)的相关属性:
- resource:资源名,即授权规则的作用对象。它指定了哪些资源需要应用此授权规则。
- 这个属性是必填的,因为授权控制是针对特定的资源进行的。
- limitApp:对应的黑名单/白名单,这是授权规则的核心部分。它指定了哪些调用方(origin)被允许或拒绝访问资源。
- 在白名单模式下,只有列在limitApp中的调用方才能访问资源。
- 在黑名单模式下,列在limitApp中的调用方将被拒绝访问资源,而其他调用方则可以访问。
- 不同的origin之间用逗号分隔,如"appA,appB"。
- strategy:授权类型,决定了listApp是作为白名单还是黑名单使用。
- AUTHORITY_WHITE:白名单模式,只有列在limitApp中的调用方才能访问资源。
- AUTHORITY_BLACK:黑名单模式,列在limitApp中的调用方将被拒绝访问资源。
- 默认为白名单模式。
5.5. 自定义异常处理
因为按照默认的实现,不管限流、熔断、热点,返回的值都是Blocked by Sentinel (flow limiting),自定义可以更好的处理对应的异常
//自定义异常
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
/**
* Handle the request when blocked.
*
* @param request Servlet request
* @param response Servlet response
* @param e the block exception
* @throws Exception users may throw out the BlockException or other error occurs
*/
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
status = 401;
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
}
}
配置流控规则:单机,qps =1 1秒内请求超过1则出发控流规则
没有使用自定义异常控流
使用自定义异常
5.6 openFegin使用Sentinel
Sentinel 适配了 Feign 组件。
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加配置:
#配置文件打开 Sentinel 对 Feign 的支持:
feign:
sentinel:
enabled: true
java代码
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class)
public interface EchoService {
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
String echo(@PathVariable("str") String str);
}
@Component
public class EchoServiceFallback implements EchoService {
@Override
public String echo(@PathVariable("str") String str) {
return "echo fallback";
}