alibaba / Sentinel

A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)
https://sentinelguard.io/
Apache License 2.0
22.42k stars 8.03k forks source link

代码自定义 FlowRuleManager.loadRules(flowRules) 不生效 #3259

Open liaocyu opened 1 year ago

liaocyu commented 1 year ago

在我们得项目中,我们想要实现使用java代码得方式去自定义流控规则,而不是通过sentinel-dashboard 控制台得方式,下面是我遇到得问题

代码

@Component
public class NacosListener {

    private static final String FLOW_RULE_DATA_ID = "esb-client-flow-rules";
    private static final String FLOW_RULE_GROUP = "SENTINEL_GROUP";
    private static final String NACOS_SERVER_ADDR = "localhost:8848";
    private static final String NACOS_NAMESPACE = "36a6cffb-6ec5-4ed8-a357-f4170e2ab131";

    @Autowired
    FlowRuleNacosPublisher flowRuleNacosPublish;
    // @NacosConfigListener(dataId = FLOW_RULE_DATA_ID, groupId = FLOW_RULE_GROUP)
    @PostConstruct
    public void onConfigChange() throws NacosException {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, NACOS_SERVER_ADDR);
        properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE);

        FlowRuleListConverter flowRuleListConverter = new FlowRuleListConverter();
        // 创建 NacosDataSource 并设置转换器
        NacosDataSource<List<FlowRule>> nacosDataSource
                = new NacosDataSource<List<FlowRule>>(properties, FLOW_RULE_GROUP, FLOW_RULE_DATA_ID, flowRuleListConverter);

        // 注册监听器,监听配置变化
        nacosDataSource.getProperty().addListener(new PropertyListener<List<FlowRule>>() {
            @Override
            public void configUpdate(List<FlowRule> flowRules) {

                // 获得了 nacos 中得规则 运用规则
                try {
                    applyFlowRules(flowRules);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void configLoad(List<FlowRule> flowRules) {

                try {
                    applyFlowRules(flowRules);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

    }

    private  void applyFlowRules(List<FlowRule> flowRules) throws Exception {

        System.out.println("______________________________________________________________________");
        System.out.println(flowRules);
        System.out.println("______________________________________________________________________");

        List<FlowRuleEntity> ruleEntities = new ArrayList<>();
        flowRules.stream().forEach(item -> {
            FlowRuleEntity flowRule = new FlowRuleEntity();
            BeanUtils.copyProperties(item , flowRule);
            ruleEntities.add(flowRule);
        });

        flowRuleNacosPublish.publish("esb-client" , ruleEntities );
        FlowRuleManager.loadRules(flowRules);
    }

    private static class FlowRuleListConverter implements Converter<String, List<FlowRule>> {
        @Override
        public List<FlowRule> convert(String source) {
            // 根据从 Nacos 获取的配置信息将其转换为限流规则对象
            return JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
            });
        }
    }

}

函数解释

注册一个nacos 配置监听器用于监听我设置的 一个关于sentinel 限流规则 我在这个监听器中实现了它的首次加载方法和更新方法,都是去执行一个 applyFlowRules(flowRules) 静态函数,其中flowRules 是一个 List 类型,在applyFlowRules 方法中,我 将 flowRules 发布到 sentienl-dashboard ,并将流控规则重新加载到 内存中

问题

经由applyFlowRules(flowRules) 函数执行后,流控规则可以正常发布到控制台,但是 执行了 FlowRuleManager.loadRules(flowRules) 却不起效果,流控规则不生效,请问有什么解决方法吗?

JulieZou commented 9 months ago

排查思路:可以检查一下你的FlowRuleNacosPublisher 里面的 ConfigService 是如何创建的,如果创建时是 ConfigFactory.createConfigService(serverAddr) 是不包含namespace 配置的,需要使用:com.alibaba.nacos.api.NacosFactory#createConfigService(java.util.Properties)