当前位置: 首页 > 图灵资讯 > 技术篇> Sentinel规则Pull模式持久化

Sentinel规则Pull模式持久化

来源:图灵教育
时间:2023-06-04 09:23:07

阅读文本大约需要3分钟。我在网上看到一篇关于这个的文章:

从官网说明

 

https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel#Pull模式

 

有以下图片,总觉得例子缺少什么??

Sentinel规则Pull模式持久化_maven

经过深思熟虑,我发现无论是官方的例子还是网民的例子,都没有结合Sentinel来解释规则。现在开始操作,按照官方步骤开始操作:

 

https://github.com/alibaba/Sentinel/wiki/扩展动态规则

 

pom在微服务中.介绍xml文件

 

<dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-datasource-extension</artifactId>    <version>x.y.z</version></dependency>

 

不知道哪里出了问题,最后也没搞清楚。还有以下问题

  • 微服务连接哪个Sentinel服务?如果没有配置,可以连接默认的Sentinel服务
  • 如果Sentinel服务的ip和port发生了变化?如何配置?还没有找到具体的解释?

带着这两个问题开始学习之旅。因为基于springboot和springcloud的解释,所有的spring Cloud 为什么不用Alibaba这么好的技术呢?

0x01:olive新建项目-pull-sentinel-datasource

  • pom.介绍xml文件

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.sentinel</groupId>    <artifactId>olive-pull-sentinel-datasource</artifactId>    <version>0.0.1-SNAPSHOT</version>    <packaging>jar</packaging>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.3.RELEASE</version>        <relativePath /> <!-- lookup parent from repository -->    </parent>    <name>olive-pull-sentinel-datasource</name>    <url>http://maven.apache.org</url>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>            <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>com.alibaba.cloud</groupId>            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>            <version>2.2.1.RELEASE</version>        </dependency>        <dependency>            <groupId>com.alibaba.csp</groupId>            <artifactId>sentinel-parameter-flow-control</artifactId>            <version>1.7.1</version>        </dependency>          <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version> 1.2.68</version>        </dependency>    </dependencies></project>

 

  • 编写以下代码

常量类主要定义规则文件的目录和名称

 

package com.sentinel.olive.file;import java.util.HashMap;import java.util.Map;public class PersistenceRuleConstant {    /**     * 存储文件路径     */    public static final String storePath = System.getProperty("user.home"""sentinel\\rules\\";    /**     * 各种存储sentinel规则映射map     */    public static final Map<String,String> rulesMap = new HashMap<String,String>();    ///流控规则文件    public static final String FLOW_RULE_PATH = "flowRulePath";    //降级规则文件    public static final String DEGRAGE_RULE_PATH = "degradeRulePath";    //授权规则文件    public static final String AUTH_RULE_PATH = "authRulePath";    ///系统规则文件    public static final String SYSTEM_RULE_PATH = "systemRulePath";    //热点参数文件    public static final String HOT_PARAM_RULE = "hotParamRulePath";    static {        rulesMap.put(FLOW_RULE_PATH,storePath+"flowRule.json");        rulesMap.put(DEGRAGE_RULE_PATH,storePath+"degradeRule.json");        rulesMap.put(SYSTEM_RULE_PATH,storePath+"systemRule.json");        rulesMap.put(AUTH_RULE_PATH,storePath+"authRule.json");        rulesMap.put(HOT_PARAM_RULE,storePath+"hotParamRule.json");    }}

 

文件操作类,如果没有规则文件,创建相应的目录和相应的规则文件

 

package com.sentinel.olive.file;import java.io.File;import java.io.IOException;import java.util.Iterator;import java.util.Map;import java.util.Set;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class RuleFileUtils {     private static final Logger logger = LoggerFactory.getLogger(RuleFileUtils.class);    /**     * 方法实现说明:如果路径不存在,则创建路径     * @param filePath:存储文件的路径     */    public static void mkdirIfNotExits(String filePath) throws IOException {        File file = new File(filePath);        if(!file.exists()) {            logger.info(创建Sentinel规则目录:{}filePath);            file.mkdirs();        }    }    /**     * 方法实现说明:如果文件不存在,则创建路径     * @param ruleFileMap 存储文件的规则     */    public static void createFileIfNotExits(Map<String,String> ruleFileMap) throws IOException {        Set<String> ruleFilePathSet = ruleFileMap.keySet();        Iterator<String> ruleFilePathIter = ruleFilePathSet.iterator();        while (ruleFilePathIter.hasNext()) {            String ruleFilePathKey = ruleFilePathIter.next();            String ruleFilePath  = PersistenceRuleConstant.rulesMap.get(ruleFilePathKey).toString();            File ruleFile = new File(ruleFilePath);            if(ruleFile.exists()) {                logger.info(”创建Sentinelel 规则文件:{}ruleFile);                ruleFile.createNewFile();            }        }    }}

 

编码和解码操作规则

 

package com.sentinel.olive.file;import java.util.List;import com.alibaba.csp.sentinel.datasource.Converter;import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;import com.alibaba.csp.sentinel.slots.system.SystemRule;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.TypeReference;public class RuleListParserUtils {    /**     * 流控列表分析器     */    public static final Converter<String, List<FlowRule>> flowRuleListParser = new Converter<String, List<FlowRule>>() {        @Override        public List<FlowRule> convert(String source) {            return JSON.parseObject(source, new TypeReference<List<FlowRule>>() {            });        }    };    /**     * 流控列表 编码器     */    public static final Converter<List<FlowRule>, String> flowRuleEnCoding = new Converter<List<FlowRule>, String>() {        @Override        public String convert(List<FlowRule> source) {            return JSON.toJSONString(source);        }    };    public static final Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(source,            new TypeReference<List<DegradeRule>>() {            });    public static final Converter<List<DegradeRule>, String> degradeRuleEnCoding = new Converter<List<DegradeRule>, String>() {        @Override        public String convert(List<DegradeRule> source) {            return JSON.toJSONString(source);        }    };    public static final Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(source,            new TypeReference<List<SystemRule>>() {            });    public static final Converter<List<SystemRule>, String> systemRuleEnCoding = new Converter<List<SystemRule>, String>() {        @Override        public String convert(List<SystemRule> source) {            return JSON.toJSONString(source);        }    };    public static final Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON            .parseObject(source, new TypeReference<List<AuthorityRule>>() {            });    public static final Converter<List<AuthorityRule>, String> authorityRuleEnCoding = new Converter<List<AuthorityRule>, String>() {        @Override        public String convert(List<AuthorityRule> source) {            return JSON.toJSONString(source);        }    };    public static final Converter<String, List<ParamFlowRule>> paramFlowRuleListParser = source -> JSON            .parseObject(source, new TypeReference<List<ParamFlowRule>>() {            });//    public static final Converter<List<ParamFlowRule>, String> paramFlowRuleEnCoding = new Converter<List<ParamFlowRule>, String>() {//        @Override//        public String convert(List<ParamFlowRule> source) {//            return JSON.toJSONString(source);//        }//    };    public static final Converter<List<ParamFlowRule>, String> paramFlowRuleEnCoding = source -> encodeJson(source);    private static <T> String encodeJson(T t) {        return JSON.toJSONString(t);    }}

 

具体pull模式操作类型

 

package com.sentinel.olive.file;import java.io.FileNotFoundException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;import com.alibaba.csp.sentinel.datasource.ReadableDataSource;import com.alibaba.csp.sentinel.datasource.WritableDataSource;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;public class PullModeLocalFileDataSource implements InitFunc {    private static final Logger logger = LoggerFactory.getLogger(PullModeLocalFileDataSource.class);    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");    @Override    public void init() throws Exception {        logger.info("time:{}读取配置, sdf.format(new Date()));        try {            // 创建文件存储目录(如果路径不存在,则创建路径)            RuleFileUtils.mkdirIfNotExits(PersistenceRuleConstant.storePath);            // ()创建规则文件()            RuleFileUtils.createFileIfNotExits(PersistenceRuleConstant.rulesMap);            // 处理流控规则逻辑            dealFlowRules();            // 处理降级规则            dealDegradeRules();            // 处理系统规则            dealSystemRules();            // 热点参数规则            dealParamFlowRules();            // 授权规则            dealAuthRules();        } catch (Exception e) {            logger.error(错误原因:{} e);        }    }    /**     * 方法实现说明:处理流控规则逻辑     */    private void dealFlowRules() throws FileNotFoundException {        String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.FLOW_RULE_PATH).toString();        // 可读数据源创建流控规则        ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(ruleFilePath,                RuleListParserUtils.flowRuleListParser);        // 将可读数据源注册为Flowrulemanger 这样,当规则文件发生变化时,将规则更新到内存        FlowRuleManager.register2Property(flowRuleRDS.getProperty());        WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<List<FlowRule>>(ruleFilePath,                RuleListParserUtils.flowRuleEnCoding);        // 注册可写数据源 transport 模块的 WritableDataSourceRegistry 中.        // 当收到控制台推送规则时,Sentinel 内存将首先更新,然后在文件中写入规则.        WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);    }    // 处理降级规则    private void dealDegradeRules() throws FileNotFoundException {        String degradeRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.DEGRAGE_RULE_PATH).toString();        // 降级规则        ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(degradeRulePath,                RuleListParserUtils.degradeRuleListParser);        DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());        WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(degradeRulePath,                RuleListParserUtils.degradeRuleEnCoding);        WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);    }    // 处理系统规则    private void dealSystemRules() throws FileNotFoundException {        String systemRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.SYSTEM_RULE_PATH).toString();        // 系统规则        ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(systemRulePath,                RuleListParserUtils.systemRuleListParser);        SystemRuleManager.register2Property(systemRuleRDS.getProperty());        WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(systemRulePath,                RuleListParserUtils.systemRuleEnCoding);        WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);    }    // 热点参数规则    private void dealParamFlowRules() throws FileNotFoundException {        String paramFlowRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.HOT_PARAM_RULE).toString();        // 热点参数规则        ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(                paramFlowRulePath, RuleListParserUtils.paramFlowRuleListParser);        ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());        WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(paramFlowRulePath,                RuleListParserUtils.paramFlowRuleEnCoding);        ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);    }    private void dealAuthRules() throws FileNotFoundException {        String authFlowRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.AUTH_RULE_PATH).toString();        // 授权规则        ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(authFlowRulePath,                RuleListParserUtils.authorityRuleListParser);        AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());        WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(authFlowRulePath,                RuleListParserUtils.authorityRuleEnCoding);        WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);    }}

 

可以通过SPI扩展机制编写上述代码进行扩展,在微服务工程中进行扩展 olive-pull-sentinel-在datasourceresresources目录下创建META-INF/services目录,新文件名为com.alibaba.csp.sentinel.init.InitFunc文件。内容是Pullmodelfiledatasource类全路径名称

Sentinel规则Pull模式持久化_spring boot_02

0x02:aplication配置文件.yml

看到这张图总是解决上述问题,提供配置项,配置Sentinel服务对应的ip和端口

Sentinel规则Pull模式持久化_spring_03

0x03:创建测试控制器和springboot启动类

测试控制器

 

package com.sentinel.olive.controller;import java.util.HashMap;import java.util.Map;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class UserController {    @GetMapping("/getUser")    public Map<String, Object> getUser() {        Map<String, Object> result = new HashMap<>();        result.put("code", "000000");        result.put("message", "ok");        return result;    }}

 

springboot启动类

 

package com.sentinel.olive;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}

 

0x04:启动并测试验证

启动服务

  • sentinel-dashboard服务
  • olive-pull-sentinel-datasource微服务

验证

  • sentinel-dashboard创建规则,olive-pull-sentinel-datasource微服务检测sentinel-dashboard变化
  • 修改json规则文件的规则,sentinel-dashboard检测到json规则编码

httpp访问微服务://localhost:866/getuser接口

Sentinel规则Pull模式持久化_spring_04

访问sentinel-dashboard服务:http://127.0.0.1:8080/

Sentinel规则Pull模式持久化_spring_05

创建流控规则

Sentinel规则Pull模式持久化_spring boot_06

olive-pull-sentinel-datasource检测到流控规则的变化,并产生flowrule.json文件

Sentinel规则Pull模式持久化_spring_07

修改流控规则文件json

Sentinel规则Pull模式持久_spring_08'

sentinel-dashboard查看规则的变化

Sentinel规则Pull模式持久化_slf4j_09