关于java:聊聊如何将数据同步到apollo配置中心

36次阅读

共计 4709 个字符,预计需要花费 12 分钟才能阅读完成。

前言

落地过微服务项目的敌人,对配置核心应该都不会生疏。利用配置核心能够集中化治理配置,还能够做到配置热更新等。目前市面常见的配置核心有 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

正文完
 0