当前位置 : 主页 > 编程语言 > java >

Spring Cloud Alibaba——Sentinel规则持久化

来源:互联网 收集:自由互联 发布时间:2023-02-04
一、在生产环境中使用Sentinel 生产环境的Sentinel Dashboard需要具备下面几个特性: 1、规则管理及推送,集中管理和推送规则。 2、监控,支持可靠、快速的实时监控和历史监控数据查询。

一、在生产环境中使用Sentinel

生产环境的Sentinel Dashboard需要具备下面几个特性:

  • 1、规则管理及推送,集中管理和推送规则。
  • 2、监控,支持可靠、快速的实时监控和历史监控数据查询。
  • 3、权限控制,区分用户角色,来进行操作。

1、规则管理及推送

一般来说,规则的推送有下面三种模式:

推送模式 说明 优点 缺点 原始模式 API 将规则推送至客户端并直接更新到内存中,扩展写数据源 简单,无任何依赖 不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境 Pull 模式 扩展写数据源, 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件等 简单,无任何依赖;规则持久化 不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。 Push 模式 扩展读数据源ReadableDataSource,规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。 规则持久化;一致性;快速 引入第三方依赖

2、动态规则扩展

Sentinel的理念是开发者只需要关注资源的定义,当资源定义成功后可以动态增加各种流控降级规则。

 

Sentinel提供两种方式修改规则:

  • 1、通过API直接修改(loadRules)——手动修改。
  • 2、通过 DataSource 适配不同数据源修改——动态规则。

手动通过API修改比较直观,可以通过以下几个API修改不同的规则:

FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控规则 DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降级规则

手动修改规则(硬编码方式)一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则。示例代码如下所示:

//TODO 发布限流规则方式一:手动通过API修改 final String rule = "[\n" + " {\n" + " \"resource\": \"login\",\n" + " \"controlBehavior\": 0,\n" + " \"count\": 5.0,\n" + " \"grade\": 1,\n" + " \"limitApp\": \"default\",\n" + " \"strategy\": 0\n" + " }\n" + "]"; ConfigService configService = NacosFactory.createConfigService(serverAddr); boolean isPublishOk = configService.publishConfig(dataId, group, rule); System.out.println(isPublishOk);

上述 loadRules() 方法只接受内存态的规则对象,但更多时候规则存储在文件、数据库或者配置中心当中。DataSource 接口给我们提供了对接任意配置源的能力。相比直接通过API 修改规则,实现 DataSource 接口是更加可靠的做法。

 

我们推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource 接口端监听规则中心实时获取变更,流程如下:

原始模式

如果不做任何修改,Dashboard的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中:

这种做法的好处是简单,无依赖;坏处是应用重启规则就会消失,仅用于简单测试,不能用于生产环境。

二、DataSource扩展方式介绍

1、DataSource扩展常见的实现方式有:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是RDBMS、文件,甚至是VCS等。这样做的方式是简单,缺点是无法及时获取变更。

  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

Sentinel目前支持以下数据源扩展:

  • Pull-based: 文件、Consul
  • Push-based: ZooKeeper, Redis, Nacos, Apollo, etcd

Pull 模式

原理:

  • 扩展写数据源(WritableDataSource), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等。
  • pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry 中。

过程如下:

Pull Demo

  • 1、添加配置
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-extension</artifactId> </dependency>
  • 2、编写持久化代码,实现com.alibaba.csp.sentinel.init.InitFunc
    • 代码参考自:传送门
import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler; import com.alibaba.csp.sentinel.datasource.*; import com.alibaba.csp.sentinel.init.InitFunc; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager; import com.alibaba.csp.sentinel.slots.system.SystemRule; import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import java.io.File; import java.io.IOException; import java.util.List; /** * FileDataSourceInit for : 自定义Sentinel存储文件数据源加载类 */ public class FileDataSourceInit implements InitFunc { @Override public void init() throws Exception { // TIPS: 如果你对这个路径不喜欢,可修改为你喜欢的路径 String ruleDir = System.getProperty("user.home") + "/sentinel/rules"; String flowRulePath = ruleDir + "/flow-rule.json"; String degradeRulePath = ruleDir + "/degrade-rule.json"; String systemRulePath = ruleDir + "/system-rule.json"; String authorityRulePath = ruleDir + "/authority-rule.json"; String hotParamFlowRulePath = ruleDir + "/param-flow-rule.json"; this.mkdirIfNotExits(ruleDir); this.createFileIfNotExits(flowRulePath); this.createFileIfNotExits(degradeRulePath); this.createFileIfNotExits(systemRulePath); this.createFileIfNotExits(authorityRulePath); this.createFileIfNotExits(hotParamFlowRulePath); // 流控规则 ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>( flowRulePath, flowRuleListParser ); // 将可读数据源注册至FlowRuleManager // 这样当规则文件发生变化时,就会更新规则到内存 FlowRuleManager.register2Property(flowRuleRDS.getProperty()); WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>( flowRulePath, this::encodeJson ); // 将可写数据源注册至transport模块的WritableDataSourceRegistry中 // 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中 WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS); // 降级规则 ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>( degradeRulePath, degradeRuleListParser ); DegradeRuleManager.register2Property(degradeRuleRDS.getProperty()); WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>( degradeRulePath, this::encodeJson ); WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS); // 系统规则 ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>( systemRulePath, systemRuleListParser ); SystemRuleManager.register2Property(systemRuleRDS.getProperty()); WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>( systemRulePath, this::encodeJson ); WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS); // 授权规则 ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>( flowRulePath, authorityRuleListParser ); AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty()); WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>( authorityRulePath, this::encodeJson ); WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS); // 热点参数规则 ReadableDataSource<String, List<ParamFlowRule>> hotParamFlowRuleRDS = new FileRefreshableDataSource<>( hotParamFlowRulePath, hotParamFlowRuleListParser ); ParamFlowRuleManager.register2Property(hotParamFlowRuleRDS.getProperty()); WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>( hotParamFlowRulePath, this::encodeJson ); ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS); } /** * 流控规则对象转换 */ private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<FlowRule>>() { } ); /** * 降级规则对象转换 */ private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<DegradeRule>>() { } ); /** * 系统规则对象转换 */ private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<SystemRule>>() { } ); /** * 授权规则对象转换 */ private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<AuthorityRule>>() { } ); /** * 热点规则对象转换 */ private Converter<String, List<ParamFlowRule>> hotParamFlowRuleListParser = source -> JSON.parseObject( source, new TypeReference<List<ParamFlowRule>>() { } ); /** * 创建目录 * * @param filePath */ private void mkdirIfNotExits(String filePath) { File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } } /** * 创建文件 * * @param filePath * @throws IOException */ private void createFileIfNotExits(String filePath) throws IOException { File file = new File(filePath); if (!file.exists()) { file.createNewFile(); } } private <T> String encodeJson(T t) { return JSON.toJSONString(t); } }
  • 3、启用上述代码 resource 目录下创建 resources/META-INF/services 目录并创建文件com.alibaba.csp.sentinel.init.InitFunc ,内容为:
com.sxzhongf.sharedcenter.configuration.sentinel.datasource.FileDataSourceInit

Pull 优缺点

  • 优点

    • 1、简单,无任何依赖
    • 2、没有额外依赖
  • 缺点

  • 1、不保证一致性(规则是使用FileRefreshableDataSource定时更新,会有延迟)

  • 2、实时性不保证(规则是使用FileRefreshableDataSource定时更新)

  • 3、拉取过于频繁也可能会有性能问题

  • 4、由于文件存储于本地,容易丢失

  • 参考资料:

    • 1、ITMUCH
    • 2、Sentinel WIKI

Push 模式

生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper、Nacos、Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了:

 

推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource接口端监听规则中心实时获取变更,流程如下:

实现原理
  • 控制台推送规则到Nacos/远程配置中心
  • Sentinel client 监听Nacos配置变化,更新本地缓存

Sentinel dashboard 加工

Dashboard 规则改造主要通过2个接口:

com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher
  • Download Sentinel Source Code
  • 修改原sentinel-dashboard项目下的POM文件
<!-- for Nacos rule publisher sample --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <!--注释掉原文件中的scope,让其不仅在test的时候生效--> <!--<scope>test</scope>--> </dependency>
  • 偷懒模式:复制sentinel-dashboard项目下test下的nacos包( src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos到 src/main/java/com/alibaba/csp/sentinel/dashboard/rule下

修改NacosConfig中的指向Nacos 的ip和端口

@Configuration public class NacosConfig { @Bean public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() { return JSON::toJSONString; } @Bean public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() { return s -> JSON.parseArray(s, FlowRuleEntity.class); } @Bean public ConfigService nacosConfigService() throws Exception { //设置Nacos的ip和端口 return ConfigFactory.createConfigService("localhost:8848"); } }
  • 修改controller中的默认provider & publisher com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2中
@RestController @RequestMapping(value = "/v2/flow") public class FlowControllerV2 { @Autowired //@Qualifier("flowRuleDefaultProvider") @Qualifier("flowRuleNacosProvider") private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; @Autowired //@Qualifier("flowRuleDefaultPublisher") @Qualifier("flowRuleNacosPublisher") private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; }
  • 打开 ·/Sentinel-1.6.2/sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html·文件,修改代码:
<!--<li ui-sref-active="active" ng-if="entry.appType==0">--> <!--<a ui-sref="dashboard.flow({app: entry.app})">--> <!--<i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则 V1</a>--> <!--</li>--> ------------改为 <li ui-sref-active="active" ng-if="entry.appType==0"> <a ui-sref="dashboard.flow({app: entry.app})"> <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则 Nacos</a> </li>

Dashboard中要修改的代码已经好了。

 

重新启动 Sentinel-dashboard mvn clean package -DskipTests

相关微服务设置

  • 添加依赖
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
  • 添加配置
spring: cloud: sentinel: datasource: yibo_flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP # 规则类型,取值见:org.springframework.cloud.alibaba.sentinel.datasource.RuleType rule_type: flow yibo_degrade: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-degrade-rules groupId: SENTINEL_GROUP rule-type: degrade

测试效果

Sentinel 添加流控规则:

Nacos 查看同步的配置:

动态数据源支持

SentinelProperties 内部提供了 TreeMap 类型的 datasource 属性用于配置数据源信息。

spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json spring.cloud.sentinel.datasource.ds1.file.rule-type=flow #spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json #spring.cloud.sentinel.datasource.ds1.file.data-type=custom #spring.cloud.sentinel.datasource.ds1.file.converter-class=com.alibaba.cloud.examples.JsonFlowRuleListConverter #spring.cloud.sentinel.datasource.ds1.file.rule-type=flow spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848 spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP spring.cloud.sentinel.datasource.ds2.nacos.data-type=json spring.cloud.sentinel.datasource.ds2.nacos.rule-type=degrade spring.cloud.sentinel.datasource.ds3.zk.path = /Sentinel-Demo/SYSTEM-CODE-DEMO-FLOW spring.cloud.sentinel.datasource.ds3.zk.server-addr = localhost:2181 spring.cloud.sentinel.datasource.ds3.zk.rule-type=authority spring.cloud.sentinel.datasource.ds4.apollo.namespace-name = application spring.cloud.sentinel.datasource.ds4.apollo.flow-rules-key = sentinel spring.cloud.sentinel.datasource.ds4.apollo.default-flow-rule-value = test spring.cloud.sentinel.datasource.ds4.apollo.rule-type=param-flow

配置说明:

spring.cloud.sentinel.transport.dashboard:sentinel dashboard的访问地址,根据上面准备工作中启动的实例配置。 spring.cloud.sentinel.datasource.ds.nacos.server-addr:nacos的访问地址,根据上面准备工作中启动的实例配置。 spring.cloud.sentinel.datasource.ds.nacos.groupId:nacos中存储规则的groupId。 spring.cloud.sentinel.datasource.ds.nacos.dataId:nacos中存储规则的dataId。 spring.cloud.sentinel.datasource.ds.nacos.rule-type:该参数是spring cloud alibaba升级到0.2.2之后增加的配置,用来定义存储的规则类型。

所有的规则类型可查看枚举类:org.springframework.cloud.alibaba.sentinel.datasource.RuleType,每种规则的定义格式可以通过各枚举值中定义的规则对象来查看,比如限流规则可查看:com.alibaba.csp.sentinel.slots.block.flow.FlowRule。这里对于dataId使用了${spring.application.name}变量,这样可以根据应用名来区分不同的规则配置。

注意:

由于版本迭代关系,Github Wiki中的文档信息不一定适用所有版本。比如:并没有spring.cloud.sentinel.datasource.ds2.nacos.rule-type这个参数。所以,读者在使用的时候,可以通过查看org.springframework.cloud.alibaba.sentinel.datasource.config.DataSourcePropertiesConfiguration和org.springframework.cloud.alibaba.sentinel.datasource.config.NacosDataSourceProperties两个类来分析具体的配置内容,会更为准确。

  • Nacos中创建限流规则的配置,比如:springcloudalibaba-sentinel-nacos.json
[ { "resource":"/sentinelNacos/hello", "limitApp":"default", "grade":1, "count":3, "strategy":0, "controlBehavior":0, "clusterMode":false } ]

可以看到上面配置规则是一个数组类型,数组中的每个对象是针对每一个保护资源的配置对象,每个对象中的属性解释如下:

resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源。
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制。
  • count:限流阈值。
  • strategy:调用关系限流策略。
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)。
  • clusterMode:是否为集群模式。

参考: https://www.bookstack.cn/read/sentinel-v1.7/9eec10a866f4e671.md

https://blog.csdn.net/m0_37661458/article/details/106605477

https://www.pianshen.com/article/44641395129/

https://www.cnblogs.com/zhangpan1244/p/11228020.html

网友评论