Sentinel(源码)规则持久化到nacos

编程入门 行业动态 更新时间:2024-10-08 12:40:15

Sentinel(源码)规则<a href=https://www.elefans.com/category/jswz/34/1771330.html style=持久化到nacos"/>

Sentinel(源码)规则持久化到nacos

一、准备工作

1、Sentinel Dashboard持久化

  我们首先需要知道:在Sentinel Dashboard中配置规则之后重启应用就会丢失,所以实际生产环境中需要配置规则的持久化实现,Sentinel提供多种不同的数据源来持久化规则配置,包括file,redis、nacos、zk。

  这就需要涉及到Sentinel Dashboard的规则管理及推送功能:集中管理和推送规则sentinel-core 提供 API 和扩展接口来接收信息。开发者需要根据自己的环境,选取一个可靠的推送规则方式;同时,规则最好在控制台中集中管理。

  而规则管理推送主要有以下三种模式:

      

                (以上部分文字跟截图来源自官方wiki)

  很明显,我们需要的是第三种Push模式,即Sentinel Dashboard统一管理配置(有良好的UI界面,为什么不能统一管理呢,明显比Nacos编写json要专业),然后将规则统一推送到Nacos并持久化(生成配置文件),最后客户端监听Nacos(这一部了解使用过Nacos的话应该很熟,采用ConfigService.getConfg()方法获取配置文件),下发配置生成Rule。如下图(虚线部分不推荐):

        

  换句话说就是实现Sentinel Dashboard与Nacos之间的相互通信:

  • Sentinel Dashboard界面配置流控规则---发布/推送--->Nacos生成配置文件并持久化;
  • 通过Nacos配置文件修改流控规则---拉取--->Sentinel Dashboard界面显示最新的流控规则。

  需要注意的是:

  • 在Nacos控制台上修改流控制,虽然可以同步到Sentinel Dashboard,但是Nacos此时应该作为一个流控规则的持久化平台,所以正常操作过程应该是开发者在Sentinel Dashboard上修改流控规则后同步到Nacos,遗憾的是目前Sentinel Dashboard不支持该功能
  • 试想下,如果公司没有统一在Sentinel Dashboard或Nacos中二选一进行配置,而是一会在Sentinel Dashboard配置,一会在Nacos配置。那么就会出现很严重的问题(流控规则达不到预期,配置数据不一致),所以推荐使用Sentinel Dashboard统一界面进行配置管理流控规则

正因为Sentinel Dashboard当前版本(截至目前为止是1.8.1-SNAPSHOT)暂不支持,但是可以通过改造部分源码实现此功能,具体请看下面介绍。

2、Sentinel Dashboard流控规则源码改造须知

首先通过git拉取下载源码,导入idea工程,解析maven后观察sentinel-dashboard模块目录结构

git clone .git

github可能会很慢,如果只是研究源码了解的话,有需要源码打包的话,可以评论或私信发给你压缩包。

改造前,我们所要了解实现Sentinel Dashboard与Nacos相互通信需要经历哪些流程或者说是缺少哪些流程,我们才好对症下药,根据我的理解我归纳总结出一下几点

(1)流控规则Controller入口

  Sentinel Dashboard的流控规则下的所有操作,都会调用Sentinel-Dashboard源码中的FlowControllerV1类,这个类中包含流控规则本地化的CRUD操作;

                

 在com.alibaba.csp.sentinel.dashboard.controller.v2包下存在一个FlowControllerV2;类,这个类同样提供流控规则的CURD,与V1不同的是,它可以实现指定数据源的规则拉取和发布

        

  官方说明:

  从 Sentinel 1.4.0 开始,我们抽取出了接口用于向远程配置中心推送规则以及拉取规则:

  • DynamicRuleProvider<T>: 拉取规则
  • DynamicRulePublisher<T>: 推送规则

  以 Nacos 为例,若希望使用 Nacos 作为动态规则配置中心,用户可以提取出相关的类,然后只需在 FlowControllerV2 中指定对应的 bean 即可开启 Nacos 适配

@Autowired @Qualifier("flowRuleNacosProvider") 
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider; 
@Autowired @Qualifier("flowRuleNacosPublisher") 
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

所以根据官网说明,我们知道,FlowControllerV2依赖两个非常重要的类

  • DynamicRuleProvider:动态规则的拉取,从指定数据源中获取控制后在Sentinel Dashboard中展示。
  • DynamicRulePublisher:动态规则发布,将在Sentinel Dashboard中修改的规则同步到指定数据源中。

只需要扩展这两个类,然后集成Nacos来实现Sentinel Dashboard规则同步

(2)Sentinel Dashboard前端sidebar.html页面入口

在目录resources/app/scripts/directives/sidebar找到sidebar.html,里面有关于V1版本的请求入口:

<li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flowV1({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
</li>

 对应的JS请求如下,可以看到请求就是V1版本的Controller,那么之后的改造需要重新对应V2版本的Controller

            <!--<li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flowV1({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a></li>--><!-- 修改为flow,直接调用FlowControllerV2 --><li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flow({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a></li>

(3)Sentinel Dashboard缺少Nacos配置

在源码中虽然官方提供了test示例(即test目录)下关于Nacos等持久化示例,但是具体的实现还需要一些细节,比如在Sentinel Dashboard配置Nacos的serverAddr、namespace、groupId,并且通过Nacos获取配置文件获取服务列表等。

                

例如:NacosConfig中ConfigFactory.createConfigService("localhost")并没有实现创建具体的nacos config service,而是默认localhost

@Configuration
public class NacosConfig {@Beanpublic Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {return JSON::toJSONString;}@Beanpublic Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {return s -> JSON.parseArray(s, FlowRuleEntity.class);}@Beanpublic ConfigService nacosConfigService() throws Exception {return ConfigFactory.createConfigService("localhost");}
}

application.properties文件中也没有Nacos的相关配置

#spring settings
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true#cookie name setting
server.servlet.session.cookie.name=sentinel_dashboard_cookie#logging settings
logging.level.springframework.web=INFO
logging.file=C:\\Users\\Administrator/logs/csp/sentinel-dashboard.log
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n#auth settings
auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
# If auth.enabled=false, Sentinel console disable login
auth.username=sentinel
auth.password=sentinel# Inject the dashboard version. It's required to enable
# filtering in pom.xml for this resource file.
sentinel.dashboard.version=1.8.1-SNAPSHOT

(4)流控规则配置文件约束

在NacosConfigutils已经指定了默认的流控规则配置文件的groupId等,但是如果需要指定的话这里也需要修改

public final class NacosConfigUtil {/*** 流控规则配置文件默认在SENTINEL_GROUP组、DATA_ID以-flow-rules结尾*/public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";public static final String GROUP_ID = "SENTINEL_GROUP";// 省略}

这样我们在Sentinel客户端就可以这么配置指定流控规则配置文件约束了

spring.cloud.sentinel.datasource.flow.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.flow.nacos.data-id=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.flow.nacos.group-id=SENTINEL_GROUP
spring.cloud.sentinel.datasource.flow.nacos.data-type=json
spring.cloud.sentinel.datasource.flow.nacos.rule-type=flow
 

二、改造Sentinel Dashboard源码实现Nacos持久化

有了以上的须知以及改造前准备工作之后,我们可以开始进行改造源码,其中需要修改部分都会做相关注释

1、在pom.xml文件中去掉test scope注释

这是因为官方提供的Nacos持久化用例都是在test目录下,所以scope需要去除test,需要sentinel-datasource-nacos包的支持。之后将修改好的源码放在源码主目录下,而不是继续在test目录下。

 <!-- for Nacos rule publisher sample --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><!--<scope>test</scope>--></dependency>

2、修改前端路由配置(sidebar.html)

找到resources/app/scripts/directives/sidebar/sidebar.html文件修改,修改flowV1为flow,去掉V1,这样的话会调用FlowControllerV2接口

  <!--<li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flowV1({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a></li>--><!-- 修改为flow,直接调用FlowControllerV2 --><li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flow({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
这样就可以通过js跳转至FlowControllerV2了
     .state('dashboard.flow', {templateUrl: 'app/views/flow_v2.html',url: '/v2/flow/:app',controller: 'FlowControllerV2',resolve: {loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {return $ocLazyLoad.load({name: 'sentinelDashboardApp',files: ['app/scripts/controllers/flow_v2.js',]});}]}})

3、创建nacos配置

(1)流控配置文件约束

我们采用官方的约束,即 默认 Nacos 适配的 dataId 和 groupId 约定如下:

  • groupId: SENTINEL_GROUP
  • 流控规则 dataId: {appName}-flow-rules,比如应用名为 appA,则 dataId 为 appA-flow-rules

所以不需要修改NacosConfigUtil.java了,但这是展示是为了步骤的完整性。

(2)创建读取nacos配置的NacosPropertiesConfiguration文件并且application.properties指定配置

package com.alibaba.csp.sentinel.dashboard.rule.nacos;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "sentinel.nacos")
public class NacosPropertiesConfiguration {private String serverAddr;private String dataId;private String groupId = "SENTINEL_GROUP"; // 默认分组private String namespace;// 省略 getter/setter  
}

然后配置sentinel-dashboar/resources/application.properties中配置nacos配置,以为sentinel.nacos为前缀:

# nacos config server
sentinel.nacos.serverAddr=127.0.0.1:8848
sentinel.nacos.namespace=msdp-cloud
sentinel.nacos.group-id=SENTINEL-GROUP

(3)改造NacosConfig,创建NacosConfigService

@EnableConfigurationProperties(NacosPropertiesConfiguration.class)
@Configuration
public class NacosConfig {@Beanpublic Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {return JSON::toJSONString;}@Beanpublic Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {return s -> JSON.parseArray(s, FlowRuleEntity.class);}@Beanpublic ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration) throws Exception {Properties properties = new Properties();properties.put(PropertyKeyConst.SERVER_ADDR, nacosPropertiesConfiguration.getServerAddr());properties.put(PropertyKeyConst.NAMESPACE, nacosPropertiesConfiguration.getNamespace());return ConfigFactory.createConfigService(properties);
//        return ConfigFactory.createConfigService("localhost");}
}

NacosConfig主要做两件事:

1) 注入Convert转换器,将FlowRuleEntity转化成FlowRule,以及反向转化

2) 注入Nacos配置服务ConfigService

4、动态实现从Nacos配置中心获取流控规则——重写FlowRuleNacosProvider与FlowRuleNacosPublisher类

重写FlowRuleNacosProvider类

@Service("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {public static final Logger log = LoggerFactory.getLogger(FlowRuleNacosProvider.class);@Autowiredprivate ConfigService configService;@Autowiredprivate Converter<String, List<FlowRuleEntity>> converter;/*** 1)通过ConfigService的getConfig()方法从Nacos Config Server读取指定配置信息* 2)通过转为converter转化为FlowRule规则* @param appName* @return* @throws Exception*/@Overridepublic List<FlowRuleEntity> getRules(String appName) throws Exception {String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, 3000);log.info("obtain flow rules from nacos config:{}", rules);if (StringUtil.isEmpty(rules)) {return new ArrayList<>();}return converter.convert(rules);}
}

重写FlowRuleNacosPublisher类:

@Service("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {public static final Logger log = LoggerFactory.getLogger(FlowRuleNacosPublisher.class);@Autowiredprivate ConfigService configService;@Autowiredprivate Converter<List<FlowRuleEntity>, String> converter;/*** 通过configService的publishConfig()方法将rules发布到nacos* @param app app name* @param rules list of rules to push* @throws Exception*/@Overridepublic void publish(String app, List<FlowRuleEntity> rules) throws Exception {AssertUtil.notEmpty(app, "app name cannot be empty");if (rules == null) {return;}log.info("sentinel dashboard push rules: {}", rules);configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, converter.convert(rules));}
}

5、复制到源码主目录下

  之后需要将上述文件(com.alibaba.csp.sentinel.dashboard.test.rule.nacos)复制到com.alibaba.csp.sentinel.dashboard.rule.nacos目录下,即去掉test目录,这样是以内源码中Nacos等持久化的配置都是在test中,打包jar的时候并不会打包进去,所以需要copy到主源码目录下。

              

6、修改FlowControllerV2类,使用@Qulifier将上面配置的两个类注入进来

@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);@Autowiredprivate InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;/*@Autowired@Qualifier("flowRuleDefaultProvider")private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;@Autowired@Qualifier("flowRuleDefaultPublisher")private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;*//*** 修改默认publisher/provider为Nacos* 使用@Qualifier指定bean*/@Autowired@Qualifier("flowRuleNacosProvider")private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;@Autowired@Qualifier("flowRuleNacosPublisher")private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;// 省略      
}

7、mvn clean package打包

先install sentinel-parent保证依赖包已经install到本地repository

之后打包sentinel-dashboard模块,执行mvn clean package命令,打包成jar包

如果以上步骤嫌麻烦,或者中间过程哪里有问题,可以私信我直接要jar包。

三、流控规则持久化测试

1、编写Sentinel客户端

(1)创建springboot应用,编写pom文件如下:

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><mavenpiler.source>1.8</mavenpiler.source><mavenpiler.target>1.8</mavenpiler.target><sentinel.version>1.8.1-SNAPSHOT</sentinel.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--  sentinel核心库 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>${sentinel.version}</version></dependency><!-- 通过nacos持久化流控规则 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><version>${sentinel.version}</version></dependency><!--  sentinel AspectJ 的扩展用于自动定义资源 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>${sentinel.version}</version></dependency><!-- sentinel 整合spring cloud alibaba --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2.1.2.RELEASE</version></dependency><!-- sentinel客户端与dashboard通信依赖 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>${sentinel.version}</version></dependency></dependencies>

(2)配置nacos,配置sentinel dashboard datasource信息:

  1)bootstrap.properties中配置Nacos Config Server

spring:application:name: msdp-sys-bootcloud:sentinel:transport:port: 8719 #跟控制台交流的端口,随意指定一个未使用的端口即可dashboard: xxx.xxx.148.124:8080 # 指定控制台服务的地址datasource:dsl:nacos:server-addr: xxx.xxx.80.182:8848dataId: ${spring.application.name}-flow-rulesgroupId: DEFAULT_GROUPdata_type: jsonrule-type: flow

(3)编写SayHelloController,指定/hello资源节点

package com.cloud.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class SayHelloController {@RequestMapping("/hello")public String sayHello(){return "hello Jian";}
}

2、启动Nacos

我使用的是win10下启动nacos,之后登录Nacos

查看起初是没有${spring.application.name}-flow-rules配置文件,也没有SENTINEL-GROUP分组;

但是服务列表会sentinel客户端实例:

分配的虚拟IP与port

3、启动sentinel dashboard控制台

(1)启动sentinel dashboard

 找到target/sentinel-dashboard.jar,执行命令:

 

java -Dserver.port=6005 -Dcsp.sentinel.dashboard.server=localhost:6006 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=6007 -jar target/sentinel-dashboard.jar

具体的启动参数介绍:

  -Dserver.port=6005 控制台端口,sentinel控制台是一个spring boot程序。客户端配置文件需要填对应的配置,如:spring.cloud.sentinel.transport.dashboard=192.168.1.102:8718
  -Dcsp.sentinel.dashboard.server=localhost:6007 控制台的地址,指定控制台后客户端会自动向该地址发送心跳包。
  -Dproject.name=sentinel-dashboard  指定Sentinel控制台程序的名称
  -Dcsp.sentinel.api.port=8719 可选项,客户端提供给Dashboard访问或者查看Sentinel的运行访问的参数,默认8719

其它启动配置项,具体查看官方wiki

(2)登录sentinel dashboard配置流控规则

 1)输入localhost:6005访问sentinel dashboard控制台(登录用户/密码默认sentinel)

 2)选择sentinel菜单-流控规则-新增流控规则-输入配置-新增

  

   如图所示,我们选择QPS阈值类型,并且count为2,流控模式为默认的直接模式,流控效果快速失败(这些配置具体含义参看官网wiki)  

注意:一开始可能会空白页面,这可能是由于机器时间机制导致的,此时可能还未发送心跳,加之sentinel控制台默认的又是懒加载模式(可去除该设置),所以最好是我们访问sentinel客户端的/hello接口然后刷新页面,即访问:http://192.168.1.156:6003/hello(ip:port是由Nacos分配的虚拟地址)

4、访问/hello接口

不停刷新访问/hello接口,观察sentinel dashboard界面中的实时监控。看到有通过QPS与拒绝QPS的实时监控情况,说明该sentinel客户端已成功接入sentinel dashboard。

5、测试Sentinel Dashboard流控规则到Nacos的持久化

(1)确认Sentinel Dashboard是否能正确发布流控规则到Nacos

  在Sentinel Dashboard针对sentinel客户端的/hello资源节点已经配置了流控规则

  

  此时Nacos会对此次流控规则生成持久化配置文件,切换到Nacos-配置列表查看确实存在分组SENTINEL_GROUP下的sentinel-flow-rules配置文件

  

  点击查看具体内容,发现关键信息都是正确的,说明Sentinel Dashboard发布到Nacos通信已经打通

  

(2)确认Sentinel Dashboard从nacos拉取流控规则配置是否成功

  修改分组SENTINEL_GROUP下的sentinel-flow-rules配置文件,修改count(QPS数)为5,然后点击发布

  

  发布后切换到Sentinel Dashboard查看/hello资源点的流控规则的阈值是否发生变化

  

  明显已经发生变化,因为Sentinel Dashboard是懒加载模式,所以刷新后后台才有日志输出:

2020-12-15 19:40:11.499 INFO 11196 --- [nio-6005-exec-8] c.a.c.s.d.r.nacos.FlowRuleNacosProvider : obtain flow rules from nacos config:[{"app":"sentinel","clusterConfig":{"acquireRef useStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowInterva lMs":1000},"clusterMode":false,"controlBehavior":0,"count":2.0,"gmtCreate":1608026073444,"gmtModified":1608026073444,"grade":1,"id":2,"ip":"169.254.102.85","limitApp":"default","port": 8720,"resource":"/hello","strategy":0}] 2020-12-15 19:51:22.612 INFO 11196 --- [nio-6005-exec-9] c.a.c.s.d.r.nacos.FlowRuleNacosProvider : obtain flow rules from nacos config:[{"app":"sentinel","clusterConfig":{"acquireRef useStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowInterva lMs":1000},"clusterMode":false,"controlBehavior":0,"count":5.0,"gmtCreate":1608026073444,"gmtModified":1608026073444,"grade":1,"id":2,"ip":"169.254.102.85","limitApp":"default","port": 8720,"resource":"/hello","strategy":0}]

  这说明Sentinel Dashboard能从nacos成功拉取流控规则配置

 (3)验证流控规则是否生效

  此时我们的QPS阈值为5,也就是说1s之间内我们需要超过访问5次,则会被sentinel限流。不断访问/hello资源节点,观察返回

  

  返回Blocked By Sentinel(flow limiting)说明限流规则已经生效。此时实时监控上也会出现通过的QPS数目为5

  

更多推荐

Sentinel(源码)规则持久化到nacos

本文发布于:2024-02-19 17:10:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1765059.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:持久   源码   规则   Sentinel   nacos

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!