Sentinel规则持久化到配置中心

Sentinel默认把规则存储在jvm内存,分布式系统自然要存储在配置中心,供所有服务去拉取规则。客户端可以通过配置中心去实时监听到,同时sentinel-dashboard也能动态刷新,但是默认是不支持sentinel-dashboard推送到配置中心的,之前曾经给官方上报过issues,他们的回复是自己去扩展实现。

在这里插入图片描述

当时就没多去在意,后来才明白过来人家有实现了,只不过是商业版的,去阿里云开通AHAS即可。昨天看文档说提供的有接口供我们扩展实现,下面就演示一个sentinel-dashboard推送到配置中心的实现。这里配置中心以阿里的配置中心Nacos为例。

1.注入一个 Nacos 配置中心对象

/**
 * <p>配置Nacos配置中心对象
 *
 * @author tianqingzhao
 * @since 2021/7/4 18:26
 * @see {@link ConfigService}
 */
@Configuration
public class NacosConfig {
    
    /**
     * 这里将FlowRuleEntity转换成FlowRule才会对客户端生效
     *
     * @return
     */
    @Bean
    public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }
    
    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }
    
    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, "ip:port");
        properties.setProperty("group", "SENTINEL_GROUP");
        properties.setProperty(PropertyKeyConst.NAMESPACE, "7a7e435c-73e4-4204-9191-72ee3d4a1767");
        properties.setProperty(PropertyKeyConst.USERNAME, "nacos");
        properties.setProperty(PropertyKeyConst.PASSWORD, "nacos");
        return ConfigFactory.createConfigService(properties);
    }
}

2.Nacos配置工具类,用于获取配置和设置配置的顶层实现,可用策略模式以及模板模式具体实现,这里简单演示一下

/**
 * <p>Nacso配置工具类
 *
 * @author tianqingzhao
 * @since 2021/7/4 17:31
 */
public final class NacosConfigUtil {
    
    public static final String GROUP_ID = "SENTINEL_GROUP";
    
    public static final String FLOW_DATA_ID_POSTFIX = "-sentinel-flow";
    
    public static final String DEGRADE_DATA_ID_POSTFIX = "-sentinel-degrade";
    
    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-sentinel-param-flow";
    
    public static final String SYSTEM_FULE_DATA_ID_POSTFIX = "-sentinel-system";
    
    public static final String AUTHORITY_DATA_ID_POSTFIX = "-sentinel-authority";
    
    public static final String DASHBOARD_POSTFIX = "-dashboard";
    
    private NacosConfigUtil() {
    }
    
    /**
     * 从nacos服务上获取配置
     *
     * @param configService nacos配置服务
     * @param appName       应用微服务名称
     * @param postfix       {@link NacosConfigUtil#FLOW_DATA_ID_POSTFIX}
     * @param clazz         反序列化class类型
     * @param <T>           规则实体类泛型
     * @return
     * @throws NacosException
     */
    public static <T> List<T> getRuleEntities4Nacos(ConfigService configService, String appName, String postfix,
            Class<T> clazz) throws NacosException {
        // 去nacos注册中心获取配置
        String rules = configService
                .getConfig(genDataId(appName, postfix) + DASHBOARD_POSTFIX, NacosConfigUtil.GROUP_ID, 3000);
        
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return (List<T>) JSON.parseObject(rules, clazz);
    }
    
    /**
     * 存在规则到nacos server上
     *
     * @param configService nacos配置服务
     * @param app           微服务名称
     * @param postfix       sentinel规则后缀
     * @param rules         规则列表
     * @param <T>           规则实体类泛型
     * @throws NacosException
     */
    public static <T> void setRuleString2Nacos(ConfigService configService, String app, String postfix, List<T> rules)
            throws NacosException {
        AssertUtil.assertNotBlank(app, "app name not be empty");
        
        List<Rule> ruleList = new ArrayList<>();
        
        for (T t : rules) {
            RuleEntity ruleEntity = (RuleEntity) t;
            Rule realRule = ruleEntity.toRule();
            ruleList.add(realRule);
        }
        
        // 生成dataId
        String dataId = genDataId(app, postfix);
        
        // 发布配置
        configService.publishConfig(dataId, NacosConfigUtil.GROUP_ID, JSON.toJSONString(ruleList));
        
        // 存储,给控制台使用
        configService.publishConfig(dataId + DASHBOARD_POSTFIX, NacosConfigUtil.GROUP_ID, JSON.toJSONString(rules));
    }
    
    /**
     * 生成配置中心的dataId
     *
     * @param appName 服务名称
     * @param postfix 规则后缀
     * @return 拼接的dataId
     */
    private static String genDataId(String appName, String postfix) {
        return appName + postfix;
    }
}

3.获取配置中心的规则,首先获取一个配置中心对象,实现 DynamicRuleProvider 接口,注入我们配置的nacos配置中心,然后通过nacos的api获取规则即可。

/**
 * <p>自定义限流规则从nacos配置中心获取
 *
 * @author tianqingzhao
 * @since 2021/7/4 18:26
 * @see {@link FlowRuleEntity}
 */
@Component("customFlowRuleNacosProvider")
public class CustomFlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
    
    @Autowired
    private ConfigService configService;
    
    @Autowired
    private Converter<String, List<FlowRuleEntity>> converter;
    
    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        String rules = configService
                .getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, 3000);
        
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }
}

4.推送规则到配置中心,也是先获取一个配置中心对象,然后实现 DynamicRulePublisher 接口

/**
 * <p>自定义限流规则发布到nacos
 *
 * @author tianqingzhao
 * @since 2021/7/4 18:26
 */
@Component("customFlowRuleNacosPublisher")
public class CustomeFlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
    
    @Autowired
    private ConfigService configService;
    
    @Autowired
    private Converter<List<FlowRuleEntity>, String> converter;
    
    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID,
                converter.convert(rules));
    }
}

5.这里只演示一个限流规则的获取以及发布,在 FlowControllerV1 类里面注入我们自定义的实现

    @Autowired
    @Qualifier("customFlowRuleNacosProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
    
    @Autowired
    @Qualifier("customFlowRuleNacosPublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

获取规则的接口为get方式请求的rules
在这里插入图片描述
保存的接口为post方式的rules接口
在这里插入图片描述
注释掉之前的发布规则方法,重新去实现

    private void publishRules(String appName) throws Exception {
        List<FlowRuleEntity> rules = repository.findAllByApp(appName);
        rulePublisher.publish(appName,rules);
    }

6.先来测试从sentinel-dashboard从nacos配置中心获取规则,nacos控制台为1

在这里插入图片描述
sentinel-dashboard刷新也显示为1
在这里插入图片描述
nacos配置中心更改为10
在这里插入图片描述
sentinel-dashboard刷新也显示为10
在这里插入图片描述
再来测试sentinel-dashboard推送到nacos配置中心,控制台改为1
在这里插入图片描述
nacos配置中心也显示为1
在这里插入图片描述
然后打包即可用了。。。。。。

细心找test包下他们是有测试的,基于apollo、nacos、zookeeper等注册中心测试过,不知道是不是单元测试完成之后忘记删除了

在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值