Gateway 整合Sentine流控组件,并实现pull模式将API管理,网关流控规则,降级规则,系统规则持久化到文件

1、网关服务pom文件

点击查看代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

2、新建 PullModeLocalFileDataSource

点击查看代码
@Slf4j
public class PullModeLocalFileDataSource implements InitFunc {


    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

    @Override
    public void init() {
        log.info("time:{}读取配置", sdf.format(new Date()));
        try {
            // 创建文件存储目录(若路径不存在就创建路径)
            RuleFileUtils.mkdirIfNotExits(PersistenceRuleConstant.storePath);
            // 创建规则文件()
            RuleFileUtils.createFileIfNotExits(PersistenceRuleConstant.rulesMap);
            // 处理流控规则
            dealFlowRules();
            // 处理API规则
            dealApiRules();
            // 处理降级规则
            dealDegradeRules();
            // 处理系统规则
            dealSystemRules();
        } catch (Exception e) {
            log.error("错误原因:{}", e);
        }

    }

    private void dealApiRules() throws FileNotFoundException {
        String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.API_RULE_PATH);

        ReadableDataSource<String, Set<ApiDefinition>> flowRuleRDS = new FileRefreshableDataSource<>(ruleFilePath,
                RuleListParserUtils.apiRuleListParser);

        GatewayApiDefinitionManager.register2Property(flowRuleRDS.getProperty());

        WritableDataSource<Set<ApiDefinition>> flowRuleWDS = new FileWritableDataSource<>(ruleFilePath,
                RuleListParserUtils.apiRuleEnCoding);

        UpdateGatewayApiDefinitionGroupCommandHandler.setWritableDataSource(flowRuleWDS);
    }

    /**
     * 方法实现说明:处理流控规则逻辑
     */
    private void dealFlowRules() throws FileNotFoundException {
        String ruleFilePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.FLOW_RULE_PATH);
        // 创建流控规则的可读数据源
        ReadableDataSource<String, Set<GatewayFlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(ruleFilePath,
                RuleListParserUtils.flowRuleListParser);
        // 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
        GatewayRuleManager.register2Property(flowRuleRDS.getProperty());
        WritableDataSource<Set<GatewayFlowRule>> flowRuleWDS = new FileWritableDataSource<>(ruleFilePath,
                RuleListParserUtils.flowRuleEnCoding);

        // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
        UpdateGatewayRuleCommandHandler.setWritableDataSource(flowRuleWDS);
    }


    // 处理降级规则
    private void dealDegradeRules() throws FileNotFoundException {
        String degradeRulePath = PersistenceRuleConstant.rulesMap.get(PersistenceRuleConstant.DEGRAGE_RULE_PATH);
        // 降级规则
        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);
        // 系统规则
        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);
    }
}

3、新建常量类 PersistenceRuleConstant

点击查看代码
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<>();

    //流控规则文件
    public static final String FLOW_RULE_PATH = "gatewayFlowRulePath";


    public static final String API_RULE_PATH = "apiRulePath";

    //降级规则文件
    public static final String DEGRAGE_RULE_PATH = "degradeRulePath";


    //系统规则文件
    public static final String SYSTEM_RULE_PATH = "systemRulePath";


    static {
        rulesMap.put(FLOW_RULE_PATH, storePath + "gatewayFlowRule.json");
        rulesMap.put(DEGRAGE_RULE_PATH, storePath + "degradeRule.json");
        rulesMap.put(SYSTEM_RULE_PATH, storePath + "systemRule.json");
        rulesMap.put(API_RULE_PATH, storePath + "apiRule.json");
    }
}

4、新建操作文件工具类
点击查看代码
@Slf4j
public class RuleFileUtils {


    /**
     * 方法实现说明:若路径不存在就创建路径
     *
     * @param filePath:文件存储路径
     */
    public static void mkdirIfNotExits(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            log.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);
            File ruleFile = new File(ruleFilePath);
            if (ruleFile.exists()) {
                log.info("创建Sentinel 规则文件:{}", ruleFile);
                ruleFile.createNewFile();
            }
        }
    }
}


5、新建解析工具类 RuleListParserUtils
点击查看代码
public class RuleListParserUtils {

    /**
     * 流控列表解析器
     */
    public static final Converter<String, Set<GatewayFlowRule>> flowRuleListParser =
            source -> JSON.parseObject(source, new TypeReference<Set<GatewayFlowRule>>() {
            });

    /**
     * 流控列表 编码器
     */
    public static final Converter<Set<GatewayFlowRule>, String> flowRuleEnCoding = JSON::toJSONString;

    public static final Converter<Set<ApiDefinition>, String> apiRuleEnCoding = JSON::toJSONString;

    public static final Converter<String, Set<ApiDefinition>> apiRuleListParser = source -> {
        Set<ApiDefinition> apiDefinitionSet = new HashSet<>();
        Set<JSONObject> set = JSON.parseObject(source, Set.class);
        for (JSONObject o : set) {
            ApiDefinition apiDefinition = new ApiDefinition();
            apiDefinition.setApiName(o.getString("apiName"));
            JSONArray predicateItems = o.getJSONArray("predicateItems");
            Set<ApiPredicateItem> apiPredicateItems = new HashSet<>();
            for (Object item : predicateItems) {
                JSONObject object = (JSONObject) item;
                ApiPathPredicateItem apiPathPredicateItem = new ApiPathPredicateItem();
                apiPathPredicateItem.setMatchStrategy(object.getIntValue("matchStrategy"));
                apiPathPredicateItem.setPattern(object.getString("pattern"));
                apiPredicateItems.add(apiPathPredicateItem);
            }

            apiDefinition.setPredicateItems(apiPredicateItems);
            apiDefinitionSet.add(apiDefinition);
        }

        return apiDefinitionSet;
    };

    public static final Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(source,
            new TypeReference<List<DegradeRule>>() {
            });

    public static final Converter<List<DegradeRule>, String> degradeRuleEnCoding = JSON::toJSONString;

    public static final Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(source,
            new TypeReference<List<SystemRule>>() {
            });

    public static final Converter<List<SystemRule>, String> systemRuleEnCoding = JSON::toJSONString;

}

6、将PullModeLocalFileDataSource对应的类名添加到位于资源目录(通常是 resource 目录)下的 META-INF/services 下的 com.alibaba.csp.sentinel.init.InitFunc 文件中,比如:
com.test.init.DataSourceInitFunc

7、启动sentilel控制台,新建的规则会自动持久化到文件中

8、https://blog.csdn.net/huangjinjin520/article/details/107572592
9、修改流控规则报空指针异常问题:升级spring-cloud-alibaba版本,sentinel 1.8.0 整合网关有bug

posted @   孤独求BUG  阅读(161)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示