4

聊聊如何将数据同步到apollo配置中心

 2 years ago
source link: https://segmentfault.com/a/1190000041439933
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

聊聊如何将数据同步到apollo配置中心

落地过微服务项目的朋友,对配置中心应该都不会陌生。利用配置中心可以集中化管理配置,还可以做到配置热更新等。目前市面常见的配置中心有QConf、spring-cloud-config、diamond、disconf、apollo、nacos等。而微服务项目最常用应该是spring-cloud-config、apollo、nacos。

我们可能会有这样的应用场景,将一些配置数据先落到数据库,然后再将这些数据持久化到配置中心。这边可以分成2步走,第一步将数据落库,第二步再手动通过配置中心提供的面板,将数据写到配置中心。不过可能我们会更倾向,将数据落库后,直接将数据同步到配置中心。今天就以apollo为例,聊聊如何将数据同步到apollo配置中心

利用apollo提供的开放API进行操作

1、将我们的应用接入Apollo开放平台

Apollo管理员在 http://{portal_address}/open/manage.html 创建第三方应用,创建之前最好先查询此AppId是否已经创建。创建成功之后会生成一个token,如下图所示:

在这里插入图片描述

2、给已注册的应用授权

Apollo管理员在 http://{portal_address}/open/manage.html 页面给token赋权。赋权之后,应用就可以通过Apollo提供的Http REST接口来管理已授权的Namespace的配置了

3、应用调用Apollo Open API

以将API网关路由信息同步到apollo为例

1、创建第三方应用

创建后提示token

2、根据token给第三方应用授权操作的appId

我们授权可以操作API网关上的所有配置,授权类型为APP

3、通过apollo-openapi调用Apollo Open API

项目中pom导入apollo-openapi坐标

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-openapi</artifactId>
    <version>1.7.0</version>
</dependency>

引入后,我们就可以直接操作apollo open api了

a、查询配置项

  public long getMaxRouteRuleIndex(){
        OpenNamespaceDTO openNamespaceDTO = apolloOpenApiClient.getNamespace(appInfoProperties.getAppId(),appInfoProperties.getEnv(),appInfoProperties.getClusterName(),appInfoProperties.getNameSpaceName());
        List<OpenItemDTO> items = openNamespaceDTO.getItems();
        if(CollectionUtils.isEmpty(items)){
            return 0;
        }
        return items.stream().filter(item -> item.getKey().matches(ID_PATTERN)).count();
    }

运行单元测试

  @Test
    public void testGetMaxRouteRuleIndex(){
        long index = routeService.getMaxRouteRuleIndex();
        Assert.assertTrue(index >= 0);
    }

此时网关上的apollo面板

b、创建并发布配置项

注: apollo的创建和发布是两个不同的API

  public boolean createRouteRule(RouteRule routeRule){
        try {
            long curRouteRuleIndex = getMaxRouteRuleIndex();
            buildOpenItemDTO(ROUTE_ID_KEY,curRouteRuleIndex,routeRule.getRouteId(),true);
            buildOpenItemDTO(ROUTE_URI_KEY,curRouteRuleIndex,routeRule.getUri(),true);
            buildOpenItemDTO(ROUTE_PREDICATES_KEY,curRouteRuleIndex,routeRule.getPredicate(),true);
            buildOpenItemDTO(ROUTE_FILTERS_KEY,curRouteRuleIndex,routeRule.getFilter(),true);
            return publish("新增网关路由","新增网关路由");
        } catch (Exception e) {
           log.error("{}",e.getMessage());
        }
        return false;
    }

运行单元测试

  @Test
    public void testCreateRouteRule(){
        RouteRule routeRule = RouteRule.builder().routeId(appName)
                .uri("http://localhost:8082")
                .predicate("Path=/dashboard/**")
                .filter("StripPrefix=1").build();

        boolean isSuccess = routeService.createRouteRule(routeRule);
        Assert.assertTrue(isSuccess);
    }

查看api网关在apollo portal上的面板

发现出现一条路由配置。因为api网关做了动态路由,因此从api网关的控制台可以发现如下输出

访问一下浏览器

动态路由生效

b、更新并发布配置项

 public boolean updateRouteRule(RouteRule routeRule){
        long ruleIndex = getRouteRuleIndex(routeRule.getRouteId());
        if(ruleIndex != -1){
            try {
                buildOpenItemDTO(ROUTE_URI_KEY,ruleIndex,routeRule.getUri(),false);
                buildOpenItemDTO(ROUTE_PREDICATES_KEY,ruleIndex,routeRule.getPredicate(),false);
                buildOpenItemDTO(ROUTE_FILTERS_KEY,ruleIndex,routeRule.getFilter(),false);
                return publish("更新网关路由","更新网关路由");
            } catch (Exception e) {
                log.error("{}",e.getMessage());
            }
        }

        return false;
    }

运行单元测试

    @Test
    public void testUpdateRouteRule(){
        RouteRule routeRule = RouteRule.builder().routeId(appName)
                .uri("http://localhost:8082")
                .predicate("Path=/xxx/**")
                .filter("StripPrefix=1").build();
        boolean isSuccess = routeService.updateRouteRule(routeRule);
        Assert.assertTrue(isSuccess);
    }

查看api网关在apollo portal上的面板

可以发现此时predicate的Path已经改为xxx

查看API网关控制台

访问一下浏览器,原先访问http://localhost:8000/dashboa...会出现

改访问http://localhost:8000/xxx/ops...

说明路由已经成功发生变更

b、删除并发布配置项

 public boolean deleteRouteRule(String routeId){
        long ruleIndex = getRouteRuleIndex(routeId);

        if(ruleIndex != -1){
            try {
//                removeRouteItem(ROUTE_URI_KEY,ruleIndex);
//                removeRouteItem(ROUTE_PREDICATES_KEY,ruleIndex);
//                removeRouteItem(ROUTE_FILTERS_KEY,ruleIndex);
                buildOpenItemDTO(ROUTE_URI_KEY,ruleIndex,"http://null",false);
                buildOpenItemDTO(ROUTE_PREDICATES_KEY,ruleIndex,"Path=/-9999",false);
                return publish("删除网关路由","删除网关路由");
            } catch (Exception e) {
                log.error("{}",e.getMessage());
            }
        }

        return false;
    }
private void removeRouteItem(String key,long index){
        if(key.equalsIgnoreCase(ROUTE_PREDICATES_KEY) || key.equalsIgnoreCase(ROUTE_FILTERS_KEY)){
            key = String.format(key,index,0);
        }else{
            key = String.format(key,index);
        }
        apolloOpenApiClient.removeItem(appInfoProperties.getAppId(),appInfoProperties.getEnv(),appInfoProperties.getClusterName(),appInfoProperties.getNameSpaceName(),key,appInfoProperties.getAuthUser());
    }

注: 因为网关删除相对复杂点,涉及到路由集合重算,这边取巧采用更新成无法访问的路由。如果是物理删除直接,调用apollo的removeItem即可

apollo开放平台提供的api其实就是http restful操作,提供一系列的增删改查操作。这边有个小细节就是apollo的增删改和发布是分开操作。如果只调用增删改,则需要在portal上点发布,或者利用发布接口进行操作。更多细节可以查看apollo的开放平台链接

https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_3210-%e6%96%b0%e5%a2%9e%e9%85%8d%e7%bd%ae%e6%8e%a5%e5%8f%a3

本文提供的示例,仅做参考,不可直接用于生产环境。如果有朋友的配置中心是用nacos,也是可以实现类似的操作。因为nacos也有提供open api接口,感兴趣朋友可以查看如下链接

https://nacos.io/zh-cn/docs/open-api.html

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-sync-apollo


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK