Sentinel-客户端集成Apollo配置中心


对于Java主流框架SpringBoot,客户端可以通过spring-cloud-starter-alibaba-sentinel来快速接入Sentinel控制台,具体接入方法见下面链接,本文不做具体介绍

https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

继上篇文章介绍Dashboard如何接入Apollo后,还剩下一个问题没解决,Sentinel Dashboard将流控规则推送到Apollo配置中心后,客户端如何实时监听到规则变化

JDK SPI机制

在介绍客户端如何接入Apollo配置中心拉取流控规则之前,先介绍下JDK SPI机制

1、什么是SPI?

SPI的全名为Service Provider Interface,是JDK内置的一种服务提供发现机制,对于面向接口开发的Java来说,SPI使得开发者能够在不同模块/不同jar包对同一接口做不同实现

2、具体应用例子?

数据库驱动的加载,不同的数据库Oracle,Mysql等在Java中需要加载不同的驱动,JDK中加载驱动的顶层抽象接口为java.sql.Driver

再来看下Mysql驱动jar包中对应的实现

在这里插入图片描述
看下两个关键点

  1. META-INF/services下有一个 以接口全路径为名称的文件,这是Spring的约定,即你要使用SPI拓展接口的实现,就需要在META-INF/services新建一个以接口全路径为名称的文件
  2. 文件中内容为该接口自定义实现类的全路径,Mysql驱动中的com.mysql.fabric.jdbc.FabricMySQLDriver即为具体实现

具体原理大家可以百度,只介绍到这里,只需要知道,我们可以在自己的项目/jar包中自定义SPI接口的实现,并在META-INF/services下指定自己的实现类来拓展接口实现

Sentinel中的InitFunc

Sentinel中针对客户端的初始化操作,也预留了SPI接口com.alibaba.csp.sentinel.init.InitFunc,我们可以拓展该接口来实现客户端从Apollo中拉取规则相关逻辑,具体拉取逻辑,直接上代码,其中ApolloConfigUtil.getNamespaceName()为Apollo中存储规则的nameSpace,需要和dashboard推送规则的nameSpace一致

public class ApolloInitFunc implements InitFunc {

    @Override
    public void init() throws Exception {
        String namespaceName = ApolloConfigUtil.getNamespaceName();
        String defaultRules = "[]";
        //流控规则
        registerFlowRuleProperty(namespaceName, defaultRules);
        //系统规则
        registerSystemRuleProperty(namespaceName, defaultRules);
        //热点规则
        registerParamFlowRuleProperty(namespaceName, defaultRules);
        //降级规则
        registerDegradeRuleProperty(namespaceName, defaultRules);
        //授权规则
        registerAuthorityRuleProperty(namespaceName, defaultRules);

    }

    private void registerAuthorityRuleProperty(String namespaceName, String defaultRules) {
        ReadableDataSource<String, List<AuthorityRule>> authorityRuleDataSource = new ApolloDataSource<>(namespaceName,
                ApolloConfigUtil.getAuthorityDataId(), defaultRules, source -> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>() {
        }));
        AuthorityRuleManager.register2Property(authorityRuleDataSource.getProperty());
    }

    private void registerDegradeRuleProperty(String namespaceName, String defaultRules) {
        ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new ApolloDataSource<>(namespaceName,
                ApolloConfigUtil.getDegradeDataId(), defaultRules, source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
        }));
        DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
    }

    private void registerParamFlowRuleProperty(String namespaceName, String defaultRules) {
        ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleDataSource = new ApolloDataSource<>(namespaceName,
                ApolloConfigUtil.getParamFlowDataId(), defaultRules, source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {
        }));
        ParamFlowRuleManager.register2Property(paramFlowRuleDataSource.getProperty());
    }

    private void registerSystemRuleProperty(String namespaceName, String defaultRules) {
        ReadableDataSource<String, List<SystemRule>> systemRuleDataSource = new ApolloDataSource<>(namespaceName,
                ApolloConfigUtil.getSystemDataId(), defaultRules, source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
        }));

        SystemRuleManager.register2Property(systemRuleDataSource.getProperty());
    }

    private void registerFlowRuleProperty(String namespaceName, String defaultRules) {
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
                ApolloConfigUtil.getFlowDataId(), defaultRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        }));

        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

}

注意点如下,最好客户端FastJson版本需要和Dashboard端保持一致,否则有可能出现奇怪的问题

第二步就是在META-INF/services下新建文件,并指定实现类路径了,比较简单,就不截图了。

最好的方案是将Apollo规则拉取相关代码、以及客户端连接Dashboard的地址配置都集成到一个SpringBoot Starter中供所有项目调用的,有兴趣的可以自己实现,不懂可以问我

发布了43 篇原创文章 · 获赞 134 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/hosaos/article/details/98214686