Sentinel 1.8.1 使用篇
---楼兰文章目录
本文是整理的Sentinel当前最新版本1.8.1的各处官方资料,更注重收集一些很重要,而平时使用中不太会去关注的东西。至于如何使用,源码中有非常多的Demo,我把他们都整了了一下,Gitee仓库地址: https://gitee.com/tearwind/SCAlibabaDemo 可以参考一下。
一、Sentinel了解
了解部分主要是整合官网上的一些介绍。
什么是Sentinel
Sentinel: 官方网站https://sentinelguard.io/ 。分布式系统的流量防卫兵。随着微服务的流行,服务与服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel具有以下特征:
- 丰富的应用场景:历经阿里近十年磨练。秒杀、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。Sentinel于2012年诞生,2018年开源,到现在又增加了Sentinel的go版本和c++版本。
- 完备的实时监控:Sentinel有控制台,可以对接入应用进行应用的秒级数据,甚至500台以下规模的集群的汇总运行情况。
- 广泛的开源生态:与Spring Cloud、Dubbo、GRPC等都有开箱即用的整合。
- 完善的SPI扩展点:Sentinel有完善的SPI扩展接口,可以通过实现扩展接口来快速定制逻辑,如规则管理、适配动态数据源等。
另外,Sentinel是阿里的一个开源项目,阿里另外有一个云上的版本AHAS,可以在阿里云上直接申请试用。AHAS和开源的Sentinel有不同的maven依赖。
Sentinel与Hystrix比较
相同点:Sentinel和Hystrix的功能定位是一致的,当检测到微服务调用链路中某个资源出现了不稳定的表现,例如请求响应时间长或者异常比例升高等情况,则对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源,而导致服务级联故障。
而两者的区别,会体现在实现手段的方方面面上。而在功能定位方面,两者最为核心的区别在于以下这几点:
- Hystrix关注的是隔离和熔断为主的容错机制,资源定义与隔离规则是强依赖的,也就是说在创建HystrixCommand的时候就指定了隔离资源与规则。
而Sentinel的设计则更为简单,资源定义与隔离规则是完全分离的,可以通过自由组合实现更多样化的控制指标和隔离规则。 - Hystrix的熔断隔离功能采用熔断器模式,在某个服务失败比率高时会自动进行熔断。而Sentinel的熔断降级功能则更为通用,支持平均响应时间和失败比率两个指标。
- 两者功能集合相比,Hystrix有点像一个功能框架,而Sentinel则更像一个综合的熔断管理框架。Sentinel本身实现了很多种规则,并且通过扩展机制,可以扩展出更多的自定义规则。Sentinel内部会平等的对待内部已有的规则实现与这些动态扩展的规则实现,然后还可以配合DashBoard对规则进行实时管理更新。
Sentinel功能依赖
Sentinel分两个部分:
- 核心库(java客户端)不依赖于任何框架,能够运行于所有Java运行时环境,同时对Dubbo、Spring Cloud等框架也有较好的支持。
- 控制台(DashBoard)是基于Spring Boot开发的一个WEB应用,打包后就可以直接运行,不需要额外的容器。
Sentinel的这两个部分之间也是没有强依赖的,但是,两个部分合作可以有更好的效果。
Sentinel的基础概念
- 资源
资源是Sentinel的关键资源,他可以是java程序中的任何内容。例如应用提供的服务或者要调用的其他应用的服务,甚至可以是一段代码。
只要通过Sentinel API定义的代码,就是一个资源,能够被Sentinel保护起来。大部分情况下,可以使用方法签名、URL、服务名称等作为资源名来标识一个资源。
- 规则
围绕资源的实时状态设定的规则,可以包括流量规则、熔断降级规则以及xtong保护规则。所有规则可以动态实时调整。
Sentinel如何工作
-
对主流框架提供适配或者显示的API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链分析。
-
根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel提供开放的接口,方便定义和改变规则。
-
Sentinel提供实时的监控系统,方便快速了解当前系统的状态。
二、Sentinel基础使用
Sentinel 核心功能
-
流量控制
流量控制主要有以下几个角度:
- 资源的调用关系。ilru资源的调用链路,资源和资源之间的关系
- 运行指标。例如QPS、线程池、系统负载等
- 控制的效果。例如直接限流、冷启动、排队等
Sentinel的设计理念就是让应用可以自由选择控制的角度,并进行灵活组合,从而达到想要的效果。
-
熔断降级
及时对调用链路中的不稳定因素进行熔断。如果调用链路中的某个资源出现不稳定,可能会导致请求发生堆积,进而导致级联错误。
Sentinel采取的手段: 1、通过并发线程数进行整体限制。对比Hytrix,采用线程池的方式对每个依赖(对应Sentinel中的资源)进行单独的隔离,Sentinel会整体限制并发线程数。当线程在特定资源上堆积到了一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
2、通过响应时间对资源进行降级。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口后才重新恢复。
-
系统自适应保护
当系统负载较高时,如果还持续有请求进来,可能会导致修改崩溃,无法响应。在集群环境中,一个节点服务崩溃,会将服务压力转发到其他机器上,加大其他机器的压力。而这些增加的流量又有可能会导致这些新机器也崩溃,最后导致整个集群不可用。
针对这种情况,Sentinel提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围内处理更多的请求。
从这一点来说, Nacos中对于服务注册的保护阈值机制也是基于同样的一种思想。
Sentinel的入门使用
Demo工程中整理了很多Demo,有官方的,也有网上大神的,还有Demo中的应用场景自己的,可以去参考下。
Sentinel的核心库maven依赖如下:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
通用的用法分三步:1 定义资源, 2 定义规则,3 检验规则是否生效
1、资源定义
资源是Sentinel中的一个重要概念,所有限流功能都是针对资源而言的。这里所说的资源,可以是java中的任何东西,接口、服务、方法、甚至是一段代码,都可以定义Sentinel中的资源。只要有了资源,就可以对资源配置各种流量控制规则,对资源进行保护。在编程时,只需要考虑代码是否需要保护,如果需要保护,就将他定义成一个资源。用户只需要考虑如何定义资源和规则,剩下的统统交给Sentinel处理就可以了。并且,在Sentinel中,资源和规则是完全解耦的,而规则是可以在运行时动态修改的。
这里就省略点官方的示例代码吧。只总结下怎么用。官方说明地址:https://github.com/alibaba/Sentinel/wiki/如何使用 定义资源的方式有以下几种:
1.主流框架的默认适配
Sentinel对大部分的主流框架进行了适配,如WEB Servlet、Dubbo、Spring Cloud、gRPC等,具体可以看下源码的sentinel-adapter模块部分。例如Dubbo,Sentinel与Dubbo集成后,不需要任何配置,就会直接将各个服务的全类名定义成资源。
2.抛出异常的方式定义资源
SphU 包含了 try-catch 风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。示例代码如下:
// 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
// 被保护的业务逻辑
// do something here...
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 在此处进行相应的处理操作
}
这种try-with-resources的方式会在代码执行结束后自动关闭entry.
若entry的时候传入了热点参数,那么exist的时候也一定要带上对应的参数,否则可能会有统计错误。
Sphu.entry()的参数:
参数名 | 类型 | 解释 | 默认值 |
---|---|---|---|
entryType | EntryType | EntryTYpe.IN入口流量,EntryTYpe.OUT出口流量,系统规则只对IN生效 | EntryType.OUT |
count | int | 本次资源调用请求的token数目 | 1 |
args | Object[] | 传入的参数,用于热点参数限流 | 无 |
这种方式尤其要注意,定义entry后必须要关闭,且参数要匹配,否则会抛出ErrorEntryFreeException异常。
3.返回布尔值方式定义资源
// 资源名可使用任意有业务语义的字符串
if (SphO.entry("自定义资源名")) {
// 务必保证finally会被执行
try {
/**
* 被保护的业务逻辑
*/
} finally {
SphO.exit();
}
} else {
// 资源访问阻止,被限流或被降级
// 进行相应的处理操作
}
这种方式同样要注意SphU.entry(xxx)需要与Sphu.exit()方法成对出现,匹配调用,位置正确,否则会抛出ErrorEntryFreeException异常。
注意 SphU 和 SphO 两个对象的定义方式。这两个对象定义资源的底层逻辑基本是一样的,只是上层的使用方式是不通过的。
4.注解方式定义资源
// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
throw new RuntimeException("getUserById command failed");
}
// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
return new User("admin");
}
这是一种典型的SpringCloud风格的资源定义方式,基于Spring的AOP机制实现的。可以用过@SentinelResource注解定义资源,配置blockHandler和fallback函数。这里blockHandler函数会在原方法被限流\降级\系统保护的时候调用,而fallback函数会针对所有类型的异常。这两个函数的定义参数必须与原方法一致,并且最后多一个BlockException参数。
5.异步调用支持
try {
AsyncEntry entry = SphU.asyncEntry(resourceName);
// 异步调用.
doAsync(entry, result -> {
try {
// 在此处处理异步调用的结果.
} finally {
// 在回调结束后 exit.
entry.exit();
}
});
} catch (BlockException ex) {
// Request blocked.
// Handle the exception (e.g. retry or fallback).
}
异步调用时,由于是在不同线程,会涉及到Context切换的问题,这时可以使用ContextUtil类来进行Context切换。示例代码:
public void handleResult(String result) {
Entry entry = null;
try {
entry = SphU.entry("handleResultForAsync");
// Handle your result here.
} catch (BlockException ex) {
// Blocked for the result handler.
} finally {
if (entry != null) {
entry.exit();
}
}
}
public void someAsync() {
try {
AsyncEntry entry = SphU.asyncEntry(resourceName);
// Asynchronous invocation.
doAsync(entry, result -> {
// 在异步回调中进行上下文变换,通过 AsyncEntry 的 getAsyncContext 方法获取异步 Context
ContextUtil.runOnContext(entry.getAsyncContext(), () -> {
try {
// 此处嵌套正常的资源调用.
handleResult(result);
} finally {
entry.exit();
}
});
});
} catch (BlockException ex) {
// Request blocked.
// Handle the exception (e.g. retry or fallback).
}
}
之所以把这个点也列在这里,主要是要体现一下SphU和SphO的区别。这两个奇怪的名字总是让人概念混乱。
2、规则定义
Sentinel的所有规则可以在内存中动态查询及修改,修改后立即生效。同时Sentinel也提供了相关API,可以定制规则。另外,DashBoard控制台中也可以给应用配置规则。
规则的API比较简单,基本的模式都是通过XXXRuleManager的静态方法loadRule来加载各种Rule。
Sentinel的规则有以下几种:流量控制规则FlowRule,熔断降级规则DegradeRule,系统保护规则SystemRule,来源访问控制规则AuthorityRule 和 热点参数规则ParamFlowRule
他们的作用从字面上也能看出个大概。把这几个名字记住,Sentinel的规则使用就记住了大半。
1> 流量控制规则FlowRule
规则管理: FlowRuleManager
示例代码:–其他规则也都差不多,只是参数有点不同。
private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(resourceName);
// set limit qps to 20
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
重要属性:
Field | 说明 | 默认值 |
---|---|---|
reource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值模式 QPS或者线程 | QPS |
limitApp | 流控针对的调用来源 | default,代表不区分调用来源 |
strategy | 调用关系限流策略 直接、连续、关联 | 直接-根据资源本身 |
controlBehivior | 流控效果(直接拒绝、排队等待、慢启动模式),不支持按调用关系限流 | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
同一个资源可以有多个限流规则,检查规则时会依次检查。
2> 熔断降级规则DegradeRule
规则管理: DegradeRuleManager
DegradeRule的重要属性:
Field | 说明 | 默认值 |
---|---|---|
resource | 资源名,即限流规则的作用对象 | |
count | 阈值 | |
grade | 熔断策略,支持秒级 RT/秒级异常比例/分钟级异常数 | 秒级平均 RT |
timeWindow | 降级的时间,单位为 s | |
rtSlowRequestAmount | RT 模式下 1 秒内连续多少个请求的平均 RT 超出阈值方可触发熔断(1.7.0 引入) | 5 |
minRequestAmount | 异常熔断的触发最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
同一个资源也可以有多个熔断降级规则
3> 系统保护规则SystemRule
规则管理: SystemRuleManager
系统自适应限流从整体维度对应用入口流量进行控制,结合用用的Load,CPU使用率,总体平均RT,入口QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。只针对入口资源EntryType=IN的生效。
系统规则包含以下几个重要属性
Field | 说明 | 默认值 |
---|---|---|
highestSystemLoad | load1 触发值,用于触发自适应控制阶段 | -1 (不生效) |
avgRt | 所有入口流量的平均响应时间 | -1 (不生效) |
maxThread | 入口流量的最大并发数 | -1 (不生效) |
qps | 所有入口资源的 QPS | -1 (不生效) |
highestCpuUsage | 当前系统的 CPU 使用率(0.0-1.0) | -1 (不生效) |
4> 访问控制规则AuthorityRule
就是资源的黑白名单
主要有以下配置项
- resource 资源名
- limitApp 对应的黑白名单,不同origin用,分隔。
- strategy 限制模式,AUTHORITY_WHITE白名单,AUTHORITY_BLACK黑名单。默认为白名单
5> 热点参数规则ParamFlowRule
示例代码:
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setParamIdx(0)
.setCount(5);
// 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
.setClassType(int.class.getName())
.setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
热点数据即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的TOP K数据,并对其访问进行限制。例如最常购买的商品ID,一段时间内访问频繁的用户ID等。热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel会利用LRU策略统计最近最常访问的热点参数,结合令牌桶算法进行参数级别的流量控制。热点参数限流支持集群模式。
使用时需要引入依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>x.y.z</version>
</dependency>
定义资源时可以在Sphu.entry方法后面传入参数,而@SentinelResource方式定义资源,则方法上的参数就会作为传入参数。
热点参数规则的属性类似于流量控制规则
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,必填 | |
count | 限流阈值,必填 | |
grade | 限流模式 | QPS 模式 |
durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 | 快速失败 |
maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 | 0ms |
paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 | |
paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型 | |
clusterMode | 是否是集群参数流控规则 | false |
clusterConfig | 集群流控相关配置 |
3、查询规则
Sentinel提供了对所有资源的实时监控。如果需要监控,客户端需要引入如下依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>x.y.z</version>
</dependency>
引入transport模块后,客户端便会主动连接Sentinel的控制台。通常不需要关注他的HTTP接口。也可以通过以下http接口获取已加载的规则:
http://localhost:8719/getRules?type= type为flow , degrade , system
http://localhost:8719/getParamRules 获取所有热点规则
4、定制持久化规则
上面定义的规则配置,都是在内存中。即应用重启后规则就会失效。可以通过sentinel提供的DataSource接口方式,将自定义规则进行持久化存储。 使用方式参见Demo代码。
官方建议
- 整合动态配置系统,如zookeeper, Nacos , Apollo等,动态地实时刷新配置规则。也支持spring cloud config。
- 结合RDBMS , NoSQL, VCS等来实现
- 配合DashBoard使用
5、规则生效的效果
1> 判断限流降级异常
在 Sentinel 中所有流控降级相关的异常都是异常类 BlockException 的子类:
- 流控异常:FlowException
- 熔断降级异常:DegradeException
- 系统保护异常:SystemBlockException
- 热点参数限流异常:ParamFlowException
我们可以通过以下函数判断是否为 Sentinel 的流控降级异常:
BlockException.isBlockException(Throwable t);
除了在业务代码逻辑上看到规则生效,我们也可以通过下面简单的方法,来校验规则生效的效果:
1.1>>暴露的 HTTP 接口:
通过运行下面命令
curl http://localhost:8719/cnode?id=<资源名称>
观察返回的数据。如果规则生效,在返回的数据栏中的 block 以及 block(m) 中会有显示
1.2>>日志:Sentinel 提供秒级的资源运行日志以及限流日志
2> block 事件
Sentinel 提供以下扩展接口,可以通过 StatisticSlotCallbackRegistry 向 StatisticSlot 注册回调函数:
ProcessorSlotEntryCallback: callback when resource entry passed (onPass) or blocked (onBlocked)
ProcessorSlotExitCallback: callback when resource entry successfully completed (onExit)
可以利用这些回调接口来实现报警等功能,实时的监控信息可以从 ClusterNode 中实时获取。
动态规则扩展
Sentinel可以通过XXXRuleManager.loadRule(List rules)的方式定义规则,同时这几个API也可以实时更新规则。但是这种硬编码的方式一般仅用于测试和演示环境,生产上一般都需要通过动态规则源的方式来动态管理规则。
Sentinel提供了DataSource接口来提供对接任意配置源的能力。应用通过控制台设置规则后将规则推送到统一的规则中心,客户端实现ReadableDataSource接口端监听规则中心实时获得变更的规则。
DataSource扩展有两种常见的实现方式:
1>拉模式,客户端主动向某个规则管理中心定期轮训拉取规则。这种方式比较简单,缺点是无法及时获取变更。目前Sentinle支持的拉模式数据源扩展有 文件和 Consul.
2>推模式,由规则中心统一推,客户端通过注册监听的方式时刻监听规则变化。目前支持的扩展配置中心有 Zookeeper,Reids,Nacos,Apollo,etcd
实现方式客户端首选需要引入以下依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>x.y.z</version>
</dependency>
然后对于拉模式,增加以下依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>x.y.z</version>
</dependency>
然后定义一个继承于AutoRefreshDataSource抽象类的数据源,通过实现readSource()方法来获取数据源。
而对于推模式,需要增加对应的sentinel-datasource-XXX依赖。例如对Nacos:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>x.y.z</version>
</dependency>
引入依赖后,就可以创建NacosReource并将其注册到对应的RuleManager上。
// remoteAddress 代表 Nacos 服务端的地址
// groupId 和 dataId 对应 Nacos 中相应配置
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
其他数据源可以参考Demo
Sentinel DashBoard 控制台
Sentinel的控制台是一个轻量级的开源控制台,主要有以下功能:
- 查看机器列表以及健康情况
- 监控单机和集群,实现秒级的实时监控
- 规则管理和推送,统一管理推送规则
- 鉴权
启动控制台
控制台jar包可以从https://github.com/alibaba/Sentinel/releases页面下载,也可以用源码进行Maven编译,编译指令mvn clean package
获取jar包后,通过以下指令启动
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
这个指令会启动控制台服务,同时将控制台应用作为一个接入端也接入到Sentinel控制台。这些启动参数可以通过java指令指定,在Spring项目中也可以通过配置文件指定。几个参数的意义:
- server.port 指定控制台端口
- csp.sentinel.dashboard.server 向接入端指定控制台地址
- project.name 向控制台指定应用名称
- sentinel.dashboard.auth.username
- auth.enabled 是否开启登录鉴权
- sentinel.dashboard.auth.password 这两个是访问控制台的用户名和密码,默认都是sentinel
- server.servlet.session.timeout 用于指定spring boot服务端Session的过期时间,但是默认是s秒,可以指定为m分钟,默认是30分钟
- sentinel.dashboard.app.hideAppNoMachineMillis 是否隐藏无健康节点的应用,距离最近一次主机心跳时间的毫秒数,默认关闭
- sentinel.dashboard.removeAppNoMachineMillis 是否自动删除无健康节点的应用,距离最近一次其下节点的心跳时间毫秒数,默认关闭
- sentinel.dashboard.unhealthyMachineMillis 主机失联判定,不可,默认60000,最小值30000
- sentinel.dashboard.autoRemoveMachineMillis 距离最近心跳时间超过指定时间是否自动删除失联节点,默认关闭
- server.servlet.session.cookie.name 控制台应用的 cookie 名称,可单独设置避免同一域名下 cookie 名冲突 默认值sentinel_dashboard_cookie
启动完成后就可以访问控制台了。
Sentinel控制台云上版本AHAS访问地址 https://ahas.console.aliyun.com/。云上版本可以免费使用30天
客户端接入
按以下步骤接入:
- 引入maven依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>x.y.z</version>
</dependency>
- 配置启动的JVM参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台。
Sentinel的启动配置参数参见官方文档: https://sentinelguard.io/zh-cn/docs/general-configuration.html
他加载配置信息的顺序:
system property -> system env -> default file(classpath:sentinel.properties) -> legacy path
-
触发客户端初始化
确保客户端有访问量,Sentinel会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。从日志中可以看到这样的几行日志:
2021-05-18 10:07:47.310 INFO 1548 --- [io-10000-exec-8] o.apache.tomcat.util.http.parser.Cookie : A cookie header was received [1619327807,1619405330; sentinel_dashboard_cookie=466D9F4B47E8E74D7DFC9A857FBF01C7] that contained an invalid cookie. That cookie will be ignored. Note: further occurrences of this error will be logged at DEBUG level.
注意,还需要根据应用类型和接入方式引入对应的适配依赖,否则即使有访问量也不能被Sentinel统计。
-
查看机器列表以及健康情况
如果在控制台的机器列表中看到了机器,就表示接入成功。如果没有接入成功,可以根据${user.home}/logs/csp/sentinel-record.log.xxx日志文件来排查原因。
控制台功能
-
簇点链路 显示刚刚调用的资源(单机实时)
该页面会实时的去拉取指定客户端资源的运行情况。注意这个监控是内存态的监控,它仅仅展示启动后调用的资源。
-
实时监控
汇总资源信息(集群聚合)。该监控会汇总统一服务下的所有机器的簇点信息并进行汇总,实现秒级的实时监控。注意该监控仅存储5分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
定制的方式主要是通过访问Sentinel控制台暴露出来的一些http接口来获取监控数据。例如:
簇点列表: /clusterNode
某个簇点的详细信息: /cnode?id=xxxx
簇点调用者统计信息: /origin?id=xxxx
链路监控 /tree
实时查询秒级日志;metric?identity=XXX&startTime=XXXX&endTime=XXXX&maxLines=XXXX
注意下Sentinel的日志格式有两种:
- 资源的秒级日志:用|分隔的十一个字段,日志文件在 h o m e / l o g s / c s p / {home}/logs/csp/ home/logs/csp/{appName}- p i d − m e t r i c s . l o g . {pid}-metrics.log. pid−metrics.log.{date}.xx 形如:
1529573107000|2018-06-21 17:25:07|sayHello(java.lang.String,long)|10|3601|10|0|2|0|0|1
各字段意义为:
index | 例子 | 说明 |
---|---|---|
1 | 1529573107000 | 时间戳 |
2 | 2018-06-21 17:25:07 | 日期 |
3 | sayHello(java.lang.String,long) | 资源名称 |
4 | 10 | 每秒通过的资源请求个数 |
5 | 3601 | 每秒资源被拦截的个数 |
6 | 10 | 每秒完成调用的资源个数,包括正常结束和异常结束的情况 |
7 | 0 | 每秒资源的异常个数 |
8 | 2 | 资源平均响应时间(ms) |
9 | 0 | 该秒占用未来请求的数目(since 1.5.0) |
10 | 0 | 预留用 |
11 | 1 | 资源分类(since 1.7.0) |
- 另外有被拦截的秒级日志
日志文件在<用户目录>/logs/csp/sentinel-block.log 日志由七个用|分隔的字段组成,形如:
2014-06-20 16:35:11|1|sayHello(java.lang.String,long),FlowException,default,origin|1,0
各字段的含义:
index | 例子 | 说明 |
---|---|---|
1 | 2014-06-20 16:35:10 | 时间戳 |
2 | 1 | 该秒发生的第一个资源 |
3 | sayHello(java.lang.String,long) | 资源名称 |
4 | XXXException | 拦截的原因, 通常 FlowException 代表是被限流规则拦截,DegradeException 则表示被降级,SystemBlockException 则表示被系统保护拦截 |
5 | default | 生效规则的调用来源(参数限流中代表生效的参数) |
6 | origin | 被拦截资源的调用者,可以为空 |
7 | 61,0 | 61 被拦截的数量,0 无意义可忽略 |
3.规则管理及推送
控制台可以配置规则并推动到应用。但是这控制台的规则推送是通过应用的HTTP API接口来更改规则,这也意味着这些规则都是内存态的,应用重启后,规则规则就会丢失。这种方式在生产中是不建议使用的,通常还是建议配置动态规则配置源,通过Push模式来管理持久化的规则配置。
4.规则管理页面上的流控模式
这三种流控模式目前好像还只能从页面上配置,代码无法实现。他们的效果大概是这样:
1、直接: 这个没有什么特别的。就是做控制。
2、关联: 如果 入口资源 达到了访问阈值,就限制 资源名 对应资源的访问。-- 这个模式可以对应为读写的场景。 例如,当写操作资源紧张时,限制关联的读操作,优先保证数据正确。
3、链路: 如果 资源名 达到到了访问阈值,就限制 入口资源 对应资源的访问。-- 这个模式可以对应为多个 入口资源 访问同一个 底层资源 的场景。例如,多个请求都要下单,当下单的资源紧张时,限制 普通下单,优先保证 秒杀下单 。
这其中 链路模式 问题非常多,有不少的BUG。多个版本更迭后,情况变得更复杂。有兴趣的可以去百度,项目中不建议使用。顺便提一下,收费版本AHAS中功能就稳定很多,这也是让很多人不爽的原因。另外,像上面第3点说到的,整体就不建议在控制台进行规则配置。
三、Sentinel与其他框架集成
Sentinel与其他框架的集成适配大都体现在自动将框架的某些关键部分定义为资源。具体实现方式有些不同,可以参看Demo。下面就以Dubbo为例。
Sentinel集成Dubbo
Sentinel提供Dubbo的相关适配,主要针对Service Provider和Service Consumer实现的Filter。需要引入的Maven依赖:
对于Apache Dubbo 2.7.x及以上版本:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>x.y.z</version>
</dependency>
对于Dubbo 2.6.x及以下版本:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-dubbo-adapter</artifactId>
<version>x.y.z</version>
</dependency>
引入依赖后,不需要做任何修改,Dubbo的服务接口和方法就会成为Sentinel中的资源,在配置规则后就可以自动享受Sentinel的防护能力。如果要关闭Sentinel Dubbo Adapter的某个资源Filter,可以通过以下配置关闭对应的资源Filter:
<!-- 关闭 Sentinel 对应的 Service Consumer Filter -->
<dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/>
但是要注意,这个Sentinel Dubbo Adapter不会接入控制台,要接入控制台还是要像上面介绍的自行接入。
限流粒度可以是服务接口和服务方法两种粒度:
- 服务接口:resourceName 为 接口全限定名,如
com.alibaba.csp.sentinel.demo.dubbo.FooService - 服务方法:resourceName 为 接口全限定名:方法签名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)
另外, Sentinel Dubbo Adapter还支持配置全局的fallback函数,可以在Dubbo服务被保护的时候进行相应的fallback处理。
实现方式,用户需要实现自定义的DubboFallback接口,然后通过DubboFallbackRegistry注册即可。默认情况会直接将BlackException包装后抛出。同时,还可以配合Dubbo的fallback机制来为降级的服务提提供替代的实现。
Sentinel集成Spring Cloud
Sentinel提供了maven依赖来支持Spring Cloud
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Spring cloud alibaba默认为Sentinel整合了Servlet,RestTemplate,FeignClient和Spring WebFlux。Sentinel在Spring Cloud生态中,不仅补全了Hystrix在Servlet和RestTemplate这一块的空白,而且还完全兼容了Hystrix在FeignClient中限流降级的用法,并且支持运行时灵活配置和调整限流降级规则。具体信息可以参看下官方的Git说明文件: https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
补充、Sentinel官方推荐的一些资料
这些是从Sentinel中找到的一些官方推荐的博客资料,可以参考。
git仓库地址: https://github.com/alibaba/Sentinel
- 介绍部分:
- 体验部分:
- 示例部分:
- sentinel-zuul-example: A simple project integration Sentinel to Spring Cloud Zuul which provide Service and API Path level flow control management by tiger
- 扩展和集成部分
- sentinel-support: A support project for convenient Sentinel integration including properties file configuration, ActiveMQ integration and a JdbcDataSource implementation by cdfive
- Sentinel dashboard multi-data-source adapter: Sentinel dashboard multi-data-source adapter has integrated Apollo and Nacos configuration center for bidirectional modification persistence. Implemented by finefuture
- Sentinel Rule Annotation Support: A third-party library that supports configuring flow rule and degrade rule using annotation. Implemented by code1986
- sentinel-pigeon-adapter: A RPC framework Pigeon adapter for Sentinel including provider and invoker rate limiting implementation by wchswchs
- 博客部分:
- Sentinel 为 Dubbo 服务保驾护航 by Eric Zhao
- 在生产环境中使用 Sentinel 控制台 by Eric Zhao
- Sentinel 与 Hystrix 的对比 by Eric Zhao
- Guideline: 从 Hystrix 迁移到 Sentinel by Eric Zhao
- Sentinel 控制台监控数据持久化【MySQL】 by cdfive
- Sentinel 控制台监控数据持久化【InfluxDB】 by cdfive
- Sentinel 控制台监控数据持久化【Apollo】 by cookiejoo
- Sentinel一体化监控解决方案 CrateDB + Grafana by Young Hu
- Sentinel 源码解析系列 by houyi
- Sentinel 学习笔记 by ro9er
- 大流量下的服务质量治理 Dubbo Sentinel 初涉 by RyuGrade
- Sentinel 深入浅出系列 by shxz130
- Alibaba Sentinel RESTful 接口流控处理优化 by luanlouis
- Sentinel 控制台前端开发环境搭建 by cdfive
- 阿里 Sentinel 源码解析 by Javadoop