1. 背景
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
1. Sentinel 介绍
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。
1.1 知识
Sentinel 的组成:
- (1) Sentinel 核心库, 即基本的类库的使用。
- (2) Dashboard 控制台,即web页面的使用。
核心库介绍
本章节主要说 核心库 的使用。
使用 Sentinel 来进行资源保护,主要分为几个步骤:
- 定义资源
- 定义规则
- 检验规则是否生效
也就是说:
- 先把可能需要保护的资源定义好(即埋点)
- 之后再配置规则,规则描述了什么方式来保护资源。
- 声明了资源,后续在任何时候灵活地定义各种流量控制规则。
资源
资源:可以是指一个服务,一个服务里的方法,或者是一段代码。写代码时,考虑某段代码是否需要保护,如果需要就将之定义为一个资源。
定义资源的方式
sentinel 支持都多种方式来定义资源,常见的有:
- 方式一:整合到常见的主流框架,比如 Web Servlet、Dubbo、Spring Cloud
- 方式二:抛出异常的方式,使用 SphU 这个类的 try-catch 方式
- 方式三:返回布尔值方式定义资源,使用 SphO 提供 if-else 风格的 API
- 方式四:注解方式定义资源,使用 @SentinelResource 注解 。
- 方式五:异步调用支持,使用 SphU.asyncEntry 异步方法。
示例有:
抛出异常的方式 来定义资源
使用 SphU 这个类的 try-catch 风格的 API。当“资源”发生了限流之后会抛出 BlockException,然后捕捉异常进行限流之后的逻辑处理。
示例代码如下:
try (Entry entry = SphU.entry("resourceName")) {
// 被保护的业务逻辑
// do something here...
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 在此处进行相应的处理操作
}
规则
Sentinel 支持以下几种规则:
- 流量控制规则
- 熔断降级规则
- 系统保护规则
- 来源访问控制规则
- 热点参数规则
流量控制规则(FlowRule)
支持 QPS 模式(1)或并发线程数模式(0)。
熔断降级规则(DegradeRule)
熔断策略,支持慢调用比例/异常比例/异常数策略
系统保护规则 (SystemRule)
结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡
来源访问控制规则 (AuthorityRule)
即黑名单,白名单规则。
规则的持久化
建议和 nacos 一起使用,方法见本文后面章节。
1.2 在service层使用 Sentinel
一般java web 项目都会有 controller 层, service 层,dao层,我们要在 service 层使用的是可以这么做。
(1)添加依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
(2) 在服务层加注解:
@Service
public class TestService {
@SentinelResource(value = "sayHello")
public String sayHello(String name) {
return "Hello, " + name;
}
}
@SentinelResource 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 value 指示了一个资源名称。
@SentinelResource 还提供了其它额外的属性如 blockHandler,blockHandlerClass,fallback 用于表示限流或降级的操作
一般我们需要实现一个降级后的处理,比如上面的 fallback 指示一个降级后字符串返回值告知触发了熔断降级。
另外,Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。我们在后面用一个章节来介绍它。
1.3 和 Feign 一起使用
Sentinel 适配了组件。
(1) 先引入 spring-cloud-starter-alibaba-sentinel
的依赖
(2) 再引入feign依赖
引入 spring-cloud-starter-openfeign
依赖**,使 Sentinel starter 中的自动化配置类生效:
org.springframework.cloud
spring-cloud-starter-openfeign
(3) 配置文件打开
配置文件打开 Sentinel 对 Feign 的支持:
feign.sentinel.enabled=true
示例说明
比如下面的示例中你要了解的:
- 1.正常的业务调用: /echo/{str}。
-
- 熔断后的异常处理,指定了 fallback 处理,并返回 "echo fallback" 字符串。
详细示例:
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
public interface EchoService {
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
String echo(@PathVariable("str") String str);
}
class FeignConfiguration {
@Bean
public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback();
}
}
class EchoServiceFallback implements EchoService {
@Override
public String echo(@PathVariable("str") String str) {
return "echo fallback";
}
}
1.4 和 RestTemplate 一起使用
支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,加上 @SentinelRestTemplate 注解。
@Bean
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
说明:@SentinelRestTemplate 注解的属性
@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。
比如上面的示例指示了 ExceptionUtil.handleException 是熔断降级后的异常处理方法,该方面用明确的方法签名格式,如下:
public class ExceptionUtil {
public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) {
...
}
}
方法返回值提供了 SentinelClientHttpResponse 用于构造返回信息。
注意
应用启动的时候会检查 @SentinelRestTemplate 注解对应的限流或降级方法是否存在,如不存在会抛出异常
实际项目中也会在网关层使用,见下一章节。
2. 在 Spring Cloud Gateway 网关中使用
可以结合 Spring Cloud Gateway 一起使用。
- (1) 添加 spring-cloud-alibaba-sentinel-gateway 依赖。
- (2) 添加 spring-cloud-starter-gateway 依赖
来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效:
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
com.alibaba.cloud
spring-cloud-alibaba-sentinel-gateway
org.springframework.cloud
spring-cloud-starter-gateway
- (3) 配置文件
指定 spring.cloud.sentinel.filter.enabled 为 false
注意:
网关流控规则数据源类型是 gw-flow
,若将网关流控规则数据源指定为 flow 则不生效。
支持两种资源标识维度的限流
Sentinel 提供的 Spring Cloud Gateway 的适配模块可以提供两种资源维度的限流:
- routeId:即在 gateway 中的路由 routeId。
- 自定义分组的名称:可以利用 API 来自定义一些分组名,将URL归类在一个组下。
- 默认不支持 URL 粒度
3. sentinel 的控制台
3.1 Sentinel 控制台包含如下功能:
- 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
- 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
- 规则管理和推送:统一管理推送规则。
- 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。
3.2. 启动 sentinel 的控制台
下载最新版本的控制台 jar 包
可以从这个 release 页面 下载。
命令行启动
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456
说明:
- -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080,浏览器从这个端访问。打开页面,默认用户名和密码都是 sentinel。
3.3. 规则管理
管理和新增规则
打开 http://localhost:8080
您可以在 控制台web页 配置修改规则,进行规则管理。
点击新增规则按钮,如下:
规则的存储
默认是存储在内存的,应用重启之后该规则会丢失。建议通过一些配置来使用外部存储方式来保存。建议结合 nacos 动态实时的刷新规则。
3.4. 规则推送
规则推送分为 3 种模式,包括:
- 原始模式
- Pull 模式
- Push 模式"。
原始模式
通过 API 将规则推送至客户端并直接更新到内存中, 图例:
------> sentinel 客户端1
Sentinel ------> sentinel 客户端2
Dashboard
------> sentinel 客户端3
好处: 简单,无依赖;
坏处: 应用重启规则就会消失,不能用于生产环境
Pull模式
在客户端注册一个本地文件数据源:收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中。
本地文件数据源会定时轮询文件的变更,读取规则。
这样我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。
以本地文件数据源为例,过程如下图所示:
/---------- 在内存中更新规则(规则缓存)
/
Sentinel -----> Sentinel客户端 ----> 将规则写入本地文件 ----> 本地文件
Dashboard
好处:简单,不引入新的依赖
坏处:无法保证监控数据的一致性
Push模式
Sentinel 控制台 的规则到 统一配置中心(比如nacos),再到各个 客户端。
即: Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel
图例:
nacos
(1) / \
/ \ (2)
/ \
Sentinel |---- sentinel 客户端1
Dashboard |---- sentinel 客户端2
生产环境建议使用 PUSH 模式,改造方法见下一章节。
4. 和 nacos 集成
4.1 介绍
默认情况下,规则是存储在内存的,重启后就没了。因此在生产环境建议使用nacos 集成来使用。分成两个步骤:
- (1) 在sentinel dashboard 控制台的web管理页面创建规则,并将规则存储到nacs。需要改造sentinel 控制台。
- (2) 客户端应用获得从 nacos 推送(PUSH)而来的 “限流的配置规则”,并加载到sentinel中。
即:在sentinel dashboard 的web页设置限流规则 ---> 规则存储到 nacos ---> 再推送到客户端应用
4.2 改造 sentinel 控制台
改造的目标是:改造 sentinel 控制台,使得在控制台的web页修改的规则保存到nacos中去。
具体改造方法:略。
有同学已经改造好的在这里:https://gitee.com/schonglin/sentinel-nacos
4.3 配置客户端,读nacos数据源。
实现的目标是:从nacos 读取规则并应用到客户端应用中。
4.3.1 修改客户端服务的配置文件,添加一个数据源
下面的示例中,我添加了一个 sentinel 的数据源 ds2, 指定了 nacos服务的地址,data-id 配置文件名,规则是 rule-type 限流类型。
spring:
application:
name: business
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080 # 指定控制台地址和端口
port: 8721 # 这个端口和 Sentinel dashborad 做交互
datasource:
# 指定一个用于流控规则的数据源(来自nacos)
ds2:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
data-id: ${spring.application.name}-flow-rules # 比如流控的规则是 {appName}-flow-rules
group-id: SENTINEL_GROUP # 指定的一个分组名
data-type: json
rule-type: flow
4.3.2 在nacos中添加一个限流的配置文件,和数据源名称一致
我在nacos中添加一个限流的配置文件,名字叫做${spring.application.name}-sentinel-flow,它的格式和上面 data-id 要对应上。
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 6,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
上面的配置内容说明:
- resource:资源名
- limitApp:调用来源, default 则不区分调用来源
- grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
- count:限流阈值,和上面的类型相关
- strategy:调用关系限流策略
- controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
- clusterMode:是否为集群模式
访问几次接口后,就可以在Sentinel Dashboard 中看到在nacos中配置的规则信息,重启后也可以再次重nacos获取到配置好的规则。
我的示例demo 见: https://github.com/vir56k/java_demo/tree/master/sentinel/sentineldemo3 配合 改造后支持nacos的sentinel 来使用。
5. 参考
Sentinel 控制台
https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel
https://www.cnblogs.com/gyli20170901/p/11279576.html
https://github.com/alibaba/Sentinel/wiki/Sentinel-%E6%8E%A7%E5%88%B6%E5%8F%B0%EF%BC%88%E9%9B%86%E7%BE%A4%E6%B5%81%E6%8E%A7%E7%AE%A1%E7%90%86%EF%BC%89#%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE
https://blog.csdn.net/qq_38723394/article/details/108991518