当前位置:   article > 正文

gateway集成sentinel配置nacos持久化GatewayFlowRule规则后--GatewayFlowRule规则失效(规则的时间单位和时间粒度失效)_在nacos中持久化的规则 加载了 但是不展示

在nacos中持久化的规则 加载了 但是不展示

gateway集成sentinel配置nacos持久化GatewayFlowRule规则后–GatewayFlowRule规则失效(规则的时间单位和时间粒度失效)

原因分析

sentinel-dashboard改造的时候模仿的是官方demo中进行改造的

sentinel源码中提供的sentinel-dashboard下test的改造dmeo, 我会在添加相应的注释进行说明

@Configuration
public class NacosConfig {

    /**
     * 将FlowRuleEntity对象转换为JSON字符串
     */
    @Bean
    public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    /**
     * 将JSON字符串转换为FlowRuleEntity对象
     */
    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    /**
     * nacos配置服务, 这里指向本地nacos
     */
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService("localhost");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

按照上述风格改造后的NacosConfig

@Slf4j
@Configuration
public class NacosConfig {
    // ---------- nacos相关的配置 start ----------
    @Value("${sentinel.nacos.serverAddr}")
    private String serverAddr;

    @Value("${sentinel.nacos.username}")
    private String username;

    @Value("${sentinel.nacos.password}")
    private String password;

    @Value("${sentinel.nacos.namespace}")
    private String namespace;

    /**
     * nacos配置服务
     */
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        properties.put(PropertyKeyConst.USERNAME, username);
        properties.put(PropertyKeyConst.PASSWORD, password);
        return ConfigFactory.createConfigService(properties);
    }
    // ---------- nacos相关的配置 end ----------

    /**
     * 网关API
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<List<ApiDefinitionEntity>, String> apiDefinitionEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<ApiDefinitionEntity>> apiDefinitionEntityDecoder() {
        return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
    }

    /**
     * 网关flowRule
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
    }

    @Bean
    public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

问题就出在sentinel和nacos交互时候List<GatewayFlowRuleEntity>JSON直接发生了转换, 而实际上sentinel使用的是List<GatewayFlowRule>

原流程

查询(queryFlowRules)

Sentinel-Nacos的GatewayFlowRule规则的[增删改查]交互的原流程如下
在这里插入图片描述

改造前–dashboard从nacos获取限流规则流程 UML时序图源码

如果对使用代码编写这种时序图感兴趣的, 到时候可以考虑单独出一期教程

新增(addFlowRule)

在这里插入图片描述

改造前–dashboard同步nacos中新增限流规则 UML时序图源码

修改(updateFlowRule)

在这里插入图片描述

改造前–dashboard同步nacos中修改限流规则 UML时序图源码

删除(deleteFlowRule)

在这里插入图片描述

改造前–dashboard同步nacos中删除限流规则 UML时序图源码

解决办法

将原来的List<GatewayFlowRuleEntity><->JSON流程中修改成以下

List<GatewayFlowRuleEntity> <—> List<GatewayFlowRule> <—> JSON

存储到sentinel中就是List<GatewayFlowRule>JSON而不是原来的List<GatewayFlowRuleEntity>, 此时限流规则就可以生效了

步骤一: 修改NacosConfig

@Slf4j
@Configuration
public class NacosConfig {
    // 其他代码省略....
    
    
    // -------------- 改动 start --------------
    // 注释掉下述代码, 将修改转换规则, 应该将GatewayFlowRuleEntity转换成GatewayFlowRule再转换成JSON
    /*@Bean
    public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }*/

    /**
     * 网关flowRule
     *
     * @return
     * @throws Exception
     */
    @Bean
    public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
        return entityList -> {
            List<GatewayFlowRule> ruleList = entityList.stream()
                    .map(GatewayFlowRuleEntity::toGatewayFlowRule)
                    .collect(Collectors.toList());
            String jsonStr = JSONObject.toJSONString(ruleList);
            log.info("转换后的JSON字符串:{}", jsonStr);
            return jsonStr;
        };
    }
	// ---------- 规则转换器 end ----------
    // -------------- 改动 end --------------
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

步骤二 : 修改GatewayFlowRulesNacosProvider

将原来的GatewayFlowRulesNacosProvider类替换成

@Slf4j
@Component("gatewayFlowRulesNacosProvider")
public class GatewayFlowRulesNacosProvider {
    @Autowired
    private ConfigService configService;

    /**
     * 获取网关流控规则
     * @param app application服务名
     * @param ip ip地址
     * @param port 端口
     * @return 转换号的List<GatewayFlowRuleEntity>
     * @throws Exception
     */
    public List<GatewayFlowRuleEntity> getRules(String app, String ip, Integer port) throws Exception {
        String jsonStr = configService.getConfig(
                app + NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID,
                3000);
        if (StrUtil.isEmpty(jsonStr)) {
            return new ArrayList<>();
        }

        // 将获取到的JSON字符串转换成GatewayFlowRule列表
        List<GatewayFlowRule> ruleList = JSON.parseArray(jsonStr, GatewayFlowRule.class);
        // 将GatewayFlowRule列表转换成GatewayFlowRuleEntity列表
        List<GatewayFlowRuleEntity> entityList = ruleList.stream()
                .map(rule -> GatewayFlowRuleEntity.fromGatewayFlowRule(app, ip, port, rule))
                .collect(Collectors.toList());
        log.info("JSON字符串:{}, " +
                "JSON->List<GatewayFlowRule>:{}, " +
                "List<GatewayFlowRule>->List<GatewayFlowRuleEntity>:{},",
                jsonStr, JSONObject.toJSONString(ruleList), JSONObject.toJSONString(entityList));
        return entityList;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

步骤三: 修改GatewayFlowRuleController

// -------------- 改动 start --------------
// @Autowired
// @Qualifier("gatewayFlowRulesNacosProvider")
// private DynamicRuleProvider<List<GatewayFlowRuleEntity>> gatewayFlowProvider;

@Autowired
@Qualifier("gatewayFlowRulesNacosProvider")
private GatewayFlowRulesNacosProvider gatewayFlowProvider;
// -------------- 改动 end --------------
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

现流程

查询(queryFlowRules)

时序图如下
在这里插入图片描述

改造后–dashboard从nacos中获取限流规则 UML时序图源码

新增(addFlowRule)

在这里插入图片描述

改造后–dashboard同步nacos中新增限流规则 UML时序图源码

修改(updateFlowRule)

在这里插入图片描述

改造后–dashboard同步nacos中修改限流规则 UML时序图源码

删除(deleteFlowRule)

在这里插入图片描述

改造后–dashboard同步nacos中删除限流规则 UML时序图源码

总结

其实笔者在写这块的时候, 参考了大量的博客, 但是那些博客实现了持久化是有缺陷的, sentinel-dashboard中操作缺失能同步到nacos, 但是这里的规则是有问题的, 无法使用的, 和我们理想中的效果大相径庭, 排查的思路大概如下

  1. 开始怀疑是sentinel内存中的规则配置的优先级高级nacos中的配置 , 于是打日志查看, 发现一旦配置了nacos持久化规则(此时内存中没有配置), 那么就会出现两条规则(一条nacos中的, 一条内存中的), 但是通过修改时, 发现nacos中发生了变化, 但是内存中却没发生变化, 最终生效的还是内存当中的
  2. 怀疑是sentinl版本和Spring Boot Alibaba版本或Sping Boot版本不兼容导致的, 后续切换成对应的版本的也是不生效的
  3. 后来又去若依的官网issue(项目基于若依二开的)上查看, 上边导致失效的原因都不是我想要的
  4. 实在受不了, 最后打断点查看, 发现基于内存版本的queryFlowRules会计算intervalSec的值, 而这个值又依赖intervalintervalUnit, 最后发现有一部操作会将JSON转换成List<GatewayFlowRule>, 也就说我们JSON必须是List<GatewayFlowRule>, 到此就恍然大悟了
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/343807
推荐阅读
相关标签
  

闽ICP备14008679号