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