[Spring-Cloud-Alibaba] Sentinel 规则持久化
在之前的练习中,只要应用重启,就需要重新配置,这样在我们实际的项目是非常不实用的,那么有没有办法把我们配置的规则保存下来呢?答案是yes,那么接下来,给大家来介绍如何将sentinel规则持久化。
document: 传送门
- file datasource(文件存储)
- pull 模式
- push 模式
- nacos configuration
- apollo
file datasource
pull 模式
原理:
扩展写数据源(writabledatasource
), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 rdbms、文件 等
pull 模式的数据源(如本地文件、rdbms 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 rulemanager,将写数据源注册至 transport 的writabledatasourceregistry
中。
过程如下:
pull demo
-
step 1: 添加配置
<dependency> <groupid>com.alibaba.csp</groupid> <artifactid>sentinel-datasource-extension</artifactid> </dependency>
-
step 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存储文件数据源加载类 * * @author <a href="mailto:magicianisaac@gmail.com">isaac.zhang | 若初</a> * @since 2019/7/21 */ 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); } }
-
step 3: 启用上述代码
resource 目录下创建
resources/meta-inf/services
目录并创建文件com.alibaba.csp.sentinel.init.initfunc
,内容为:com.sxzhongf.sharedcenter.configuration.sentinel.datasource.filedatasourceinit
pull 优缺点
- 优点
- 简单,无任何依赖
- 没有额外依赖
- 缺点
- 不保证一致性(规则是使用
filerefreshabledatasource
定时更新,会有延迟) - 实时性不保证(规则是使用
filerefreshabledatasource
定时更新) - 拉取过于频繁也可能会有性能问题
- 由于文件存储于本地,容易丢失
- 不保证一致性(规则是使用
- 参考资料:
push 模式
推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现
readabledatasource
接口端监听规则中心实时获取变更,流程如下:
-
实现原理
- 控制台推送规则到nacos/远程配置中心
- sentinel client 舰艇nacos配置变化,更新本地缓存
-
shared_center service 加工
- 添加依赖
<dependency> <groupid>com.alibaba.csp</groupid> <artifactid>sentinel-datasource-nacos</artifactid> </dependency>
- 添加配置
spring: cloud: sentinel: datasource: sxzhongf_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 sxzhongf_degrade: nacos: server-addr: localhost:8848 dataid: ${spring.application.name}-degrade-rules groupid: sentinel_group rule-type: degrade
-
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
下 -
修改controller中的默认provider & publisher
com.alibaba.csp.sentinel.dashboard.controller.v2.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">--> <!--<a ui-sref="dashboard.flow({app: entry.app})">--> <!--<i class="glyphicon glyphicon-filter"></i> 流控规则 v1</a>--> <!--</li>--> --- 改为 <li ui-sref-active="active"> <a ui-sref="dashboard.flow({app: entry.app})"> <i class="glyphicon glyphicon-filter"></i> nacos 流控规则 v1</a> </li>
dashboard中要修改的代码已经好了。
重新启动 sentinel-dashboard
mvn clean package -dskiptests
-
测试效果
sentinel 添加流控规则:
nacos 查看同步的配置:
上一篇: 工厂模式的一个简单实现
下一篇: 有什么见不得人的事