当前位置: 代码网 > it编程>编程语言>Java > gateway集成sentinel配置nacos持久化GatewayFlowRule规则后--GatewayFlowRule规则失效(规则的时间单位和时间粒度失效)

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

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

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

原因分析

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

@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");
    }
}
@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;
    }
}

原流程

查询(queryflowrules)

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

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

新增(addflowrule)

在这里插入图片描述

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

修改(updateflowrule)

在这里插入图片描述

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

删除(deleteflowrule)

在这里插入图片描述

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

解决办法

步骤一: 修改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 --------------
}

步骤二 : 修改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;
    }
}

步骤三: 修改gatewayflowrulecontroller

// -------------- 改动 start --------------
// @autowired
// @qualifier("gatewayflowrulesnacosprovider")
// private dynamicruleprovider<list<gatewayflowruleentity>> gatewayflowprovider;

@autowired
@qualifier("gatewayflowrulesnacosprovider")
private gatewayflowrulesnacosprovider gatewayflowprovider;
// -------------- 改动 end --------------

现流程

查询(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>, 到此就恍然大悟了
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com