sentinel--初级使用篇
1、官方资料
github官网地址:https://github.com/alibaba/Sentinel
wiki:https://github.com/alibaba/Sentinel/wiki/
2、基本使用方式
2.1 Sentinel的初体验
引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel‐core</artifactId>
<version>1.7.1</version>
</dependency>
初始化降级规则
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule(KEY)
.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
// Set ratio threshold to 50%.
.setCount(0.5d)
.setStatIntervalMs(30000)
.setMinRequestAmount(50)
// Retry timeout (in second)
.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
使用降级
Entry entry = null;
try {
entry = SphU.entry(KEY);
throw new RuntimeException("oops");
}catch (Throwable t) {
bizException.incrementAndGet();
// It\'s required to record exception here manually.
Tracer.traceEntry(t, entry);
} finally {
total.addAndGet(1);
if (entry != null) {
entry.exit();
}
}
2.2AOP进阶版
引入注解依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel‐annotation‐aspectj</artifactId>
<version>1.7.1</version>
</dependency>
还是规则初始化
Entry entry = null;
try {
entry = SphU.entry(KEY);
throw new RuntimeException("oops");
}catch (Throwable t) {
bizException.incrementAndGet();
// It\'s required to record exception here manually.
Tracer.traceEntry(t, entry);
} finally {
total.addAndGet(1);
if (entry != null) {
entry.exit();
}
}
在对应的方法上加入对应的注解
@Override
@SentinelResource(value = "hello", fallback = "helloFallback")
public String hello(long s) {
if (s <= 0) {
throw new IllegalArgumentException("invalid arg");
}
return String.format("Hello at %d", s);
}
public String helloFallback(long s, Throwable ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
2.3 spring boot 簇点链路版
引入新的jar
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐sentinel</artifactId>
</dependency>
在application.yml中引入dashboard对应的地址
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
启动dashboard
dashboard有个确定在没有请求的时候是没有任何数据的,这里需要触发一次请求,就看到如下图的效果
使用起来非常简便,只需要加入dashboard地址即可
3、从dashboard 看sentinel所具备的功能
3.1流控设置
簇点链路 选择具体的访问的url地址 然后点击流控按钮
资源名称:为我们接口的url /selectOrderInfoById/1
针对来源:这里是默认的default(标示不针对来源),还有一种情况就是 假设微服务A需要调用这个资源,微服务B也需要调用这个资源,那么我们就可以单独的为 微服务A和微服务B进行设置阈值。
阈值类型: 分为QPS和线程数 假设阈值为2
QPS类型:只得是每秒钟访问接口的次数>2就进行限流
线程数:为接受请求该资源 分配的线程数>2就进行限流.
流控模式:
①:直接:这种很好理解,就是达到设置的阈值后直接被流控抛出异常 疯狂的请求这个路径
②:关联 业务场景 我们现在有二个api,第一个是保存订单,第二个是查询订单,假设我们希望优先操 作是"保存订单" 。例如写接口保存订单接口达到阀值就会对查询接口进行限流。相当于是对写接口的一种保护。
③:链路(用法说明,本地实验没成功)大家自己研究
流控效果:
①:快速失败(直接抛出异常) 每秒的QPS 操过1 就直接抛出异常
②:预热(warmUp)
我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系 统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到 达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。
据图的请求监控如下
③:排队等待
这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会 把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果, 而不是拒绝所有请求。
单机阈值:10表示 每秒通过的请求个数是10,那么每隔100ms通过一次请求. 每次请求的最大等待时间为20000=20s,超过20S就丢弃请求。
3.2降级
①rt(平局响应时间)
平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒 级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中 的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛 出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置
②异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):
当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中 的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
③异常数 (DEGRADE_GRADE_EXCEPTION_COUNT) :
当资源近 1 分钟的异常数目超过阈值之后 会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再 进入熔断状态。
3.3 热点参数:
秒杀业务,比如商城做促销秒杀,针对苹果12(商品id=5)进行9.9秒杀活动,那么这个时候,我们去请 求订单接口(商品id=5)的请求流量十分大,我们就可以通过热点参数规则来控制 商品id=5的请求的并发量。而其他正常商品的请求不会收到限制。那么 这种热点参数规则很使用。
4、dashboard与应用程序的简单交互
4.1原始模式
如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中:
4.2Pull模式
pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry
中。以本地文件数据源为例:
public class FileDataSourceInit implements InitFunc {
@Override public void init() throws Exception { String flowRulePath = "xxx"; ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>( flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}) ); // 将可读数据源注册至 FlowRuleManager. FlowRuleManager.register2Property(ds.getProperty()); WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson); // 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中. // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中. WritableDataSourceRegistry.registerFlowDataSource(wds); } private <T> String encodeJson(T t) { return JSON.toJSONString(t); } }
本地文件数据源会定时轮询文件的变更,读取规则。这样我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。以本地文件数据源为例,推送过程如下图所示:
首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull 模式的数据源时一般不需要对 Sentinel 控制台进行改造。
这种实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。
4.3push模式
生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了:
我们提供了 ZooKeeper, Apollo, Nacos 等的动态数据源实现。以 ZooKeeper 为例子,如果要使用第三方的配置中心作为配置管理,您需要做下面的几件事情:
- 实现一个公共的 ZooKeeper 客户端用于推送规则,在 Sentinel 控制台配置项中需要指定 ZooKeeper 的地址,启动时即创建 ZooKeeper Client。
- 我们需要针对每个应用(appName),每种规则设置不同的 path(可随时修改);或者约定大于配置(如 path 的模式统一为
/sentinel_rules/{appName}/{ruleType}
,e.g.sentinel_rules/appA/flowRule
)。 - 规则配置页需要进行相应的改造,直接针对应用维度进行规则配置;修改同个应用多个资源的规则时可以批量进行推送,也可以分别推送。Sentinel 控制台将规则缓存在内存中(如
InMemFlowRuleStore
),可以对其进行改造使其支持应用维度的规则缓存(key 为 appName),每次添加/修改/删除规则都先更新内存中的规则缓存,然后需要推送的时候从规则缓存中获取全量规则,然后通过上面实现的 Client 将规则推送到 ZooKeeper 即可。 - 应用客户端需要注册对应的读数据源以监听变更,可以参考 相关文档。
从 Sentinel 1.4.0 开始,Sentinel 控制台提供 DynamicRulePublisher
和 DynamicRuleProvider
接口用于实现应用维度的规则推送和拉取,并提供了相关的示例。Sentinel 提供应用维度规则推送的示例页面(/v2/flow
),用户改造控制台对接配置中心后可直接通过 v2 页面推送规则至配置中心。改造详情可参考 应用维度规则推送示例。
部署多个控制台实例时,通常需要将规则存至 DB 中,规则变更后同步向配置中心推送规则。