What is Apollo?
随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关、参数的配置、服务器的地址……
对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境、分集群管理配置,完善的权限、审核机制……
在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求。
Apollo配置中心应运而生!Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,具备规范的权限、流程治理等特性。
目前的几种配置中心对比如下:
功能点 | 优先级 | spring-cloud-config | ctrip apollo | disconf | 备注 |
---|---|---|---|---|---|
静态配置管理 | 高 | 基于file | 支持 | 支持 | |
动态配置管理 | 高 | 支持 | 支持 | 支持 | |
统一管理 | 高 | 无,需要github | 支持 | 支持 | |
多环境 | 中 | 无,需要github | 支持 | 支持 | |
本地配置缓存 | 高 | 无 | 支持 | 支持 | |
配置锁 | 中 | 支持 | 不支持 | 不支持 | 不允许动态及远程更新 |
配置校验 | 中 | 无 | 无 | 无 | 如:ip地址校验,配置 |
配置生效时间 | 重启生效,或手动refresh生效 | 实时 | 实时 | 需要结合热加载管理, springcloudconfig需要 git webhook+rabbitmq 实时生效 | |
配置更新推送 | 高 | 需要手工触发 | 支持 | 支持 | |
配置定时拉取 | 高 | 无 | 支持 | 配置更新目前依赖事件驱动, client重启或者server端推送操作 | |
用户权限管理 | 中 | 无,需要github | 支持 | 支持 | 现阶段可以人工处理 |
授权、审核、审计 | 中 | 无,需要github | 支持 | 无 | 现阶段可以人工处理 |
配置版本管理 | 高 | Git做版本管理 | 界面上直接提供发布历史和回滚按钮 | 操作记录有落数据库,但无查询接口 | |
配置合规检测 | 高 | 不支持 | 支持(但还需完善) | ||
实例配置监控 | 高 | 需要结合springadmin | 支持 | 支持,可以查看每个配置在哪些机器上加载 | |
灰度发布 | 中 | 不支持 | 支持 | 不支持部分更新 | 现阶段可以人工处理 |
告警通知 | 中 | 不支持 | 支持,邮件方式告警 | 支持,邮件方式告警 | |
依赖关系 | 高 | 不支持 | 不支持 | 不支持 | 配置与系统版本的依赖系统运行时的依赖关系 |
更多比较->统一配置中心选型对比
首先去官网下载3个压缩包,我是用的是目前最新的1.2.0版本(apollo-adminservice,apollo-configservice,apollo-portal):
https://github.com/ctripcorp/apollo/releases
Apollo运行还需要MySQL(5.6.5+)和Eureka,Eureka安装配置可以看我以前的博客->SpringCloud Eureka服务治理模块,MySQL需要两个库ApolloPortalDB和ApolloConfigDB,建库/表的语句在官网->apolloportaldb.sql和apolloconfigdb.sql,
导入成功后,可以通过执行以下sql语句来验证:
select `Id`, `Key`, `Value`, `Comment` from `ApolloPortalDB`.`ServerConfig` limit 1;
Id | Key | Value | Comment |
---|---|---|---|
1 | apollo.portal.envs | dev | 可支持的环境列表 |
注:ApolloPortalDB只需要在生产环境部署一个即可
select `Id`, `Key`, `Value`, `Comment` from `ApolloConfigDB`.`ServerConfig` limit 1;
Id | Key | Value | Comment |
---|---|---|---|
1 | eureka.service.url | http://127.0.0.1:8080/eureka/ | Eureka服务Url |
注:ApolloConfigDB需要在每个环境部署一套,如fat、uat和pro分别部署3套ApolloConfigDB
然后我们解压刚刚下载的3个压缩包,分别修改3个文件夹的config/application-github.properties文件的DataSource参数,修改apollo-portal-{version}-github文件夹下的config/apollo-env.properties如下:
local.meta=http://localhost:8080
dev.meta=http://127.0.0.1:8080
#fat.meta=http://fill-in-uat-meta-server:8080
#uat.meta=http://fill-in-uat-meta-server:8080
#lpt.meta=${lpt_meta}
#pro.meta=http://fill-in-pro-meta-server:8080
注:待会儿会开启3个Tomcat服务,会占用8070、8080、8090三个端口,如果需要改请修改各个文件夹下的scripts/startup.sh的SERVER_PORT参数值
分别进入三个项目启动(启动顺序:configservice->adminservice->portal):scripts/startup.sh,等待一会儿就会start了(关闭使用scripts/shutdown.sh),然后访问http://localhost:8070/即可看到登录界面,用户名/密码:apollo/admin
注:如果Eureka不在本地,需要修改ApolloConfigDB库的ServerConfig表的eureka.service.url值为真实地址,否则报错"apollo 系统出错,请重试或联系系统负责人",如果改了还有问题是由于注册到Eureka需要时间等会或者重启服务就好了
启动成功可以在Eureka看到注册消息:APOLLO-ADMINSERVICE和APOLLO-CONFIGSERVICE
创建项目(应用Id比较重要,如果是私有命名空间如默认的application空间,访问需要指定id号才能访问的到):
新增配置->添加配置项:
创建命名空间:
最后结果:
项目结构如下:
首先更新pom.xml添加一个apollo-client依赖
com.ctrip.framework.apollo
apollo-client
1.1.2
更新application.yml
server:
port: 8081
app:
# 如果有private的命名空间需要配置(默认application空间是private的)
id: 222
apollo:
# 指定apollo-configservice
meta: http://127.0.0.1:8080
启动类
package cn.yunlingfly.springbootapolloclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// 如果都是使用默认的application命名空间可以直接在启动类使用下面的注解
//@EnableApolloConfig
public class SpringbootApolloClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApolloClientApplication.class, args);
}
}
Controller层
DefaultController :
package cn.yunlingfly.springbootapolloclient.controller;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableApolloConfig
public class DefaultController {
@ApolloConfig("application")
private Config config; //inject config for namespace application
@Value("${key2:test}")//如果配置中心没有值,默认key为key2的value值为test
private String name;
//config change listener for namespace application
@ApolloConfigChangeListener("application")
private void anotherOnChange(ConfigChangeEvent changeEvent) {
ConfigChange change = changeEvent.getChange("key2");
System.out.println(String.format("Found change - key: %s, oldValue: %s,"
+ " newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
}
// 通过注解的方式
@RequestMapping(value = "/getIndex",method = RequestMethod.GET)
public String index(){
return name;
}
// 通过Api的方式(不推荐)
@RequestMapping(value = "/apiIndex",method = RequestMethod.GET)
public String apiIndex(){
// 使用默认命名空间"application"
String someKey = "key2";
String someDefaultValue = "defaultValue";
String value = config.getProperty(someKey, someDefaultValue);
return value;
}
}
NameSpaceController :
package cn.yunlingfly.springbootapolloclient.controller;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
// 指定命名空间
@EnableApolloConfig("aaa")
public class NameSpaceController {
@Value("${namespace:test}")//如果配置中心没有值,使用命名空间aaa,默认key为namespace的value值为test
private String namespace;
// 使用命名空间
@RequestMapping(value = "/namespace",method = RequestMethod.GET)
public String namespace(){
return namespace;
}
}
访问:
http://localhost:8081/getIndex(使用注解形式)
http://localhost:8081/apiIndex(使用api形式)
http://localhost:8081/namespace(测试命名空间)
更多使用访问官网:Java客户端使用指南