参考博客:https://blog.csdn.net/aaronsimon/article/details/83657612
对于传统的单体应用,通常使用配置文件管理所有配置。比如Spring Boot开发的单体应用,配置内容可以放在application.yml文件,需要切换环境的话可以设置多个Profile并在启动应用时指定spring.pfofiles.active={profile}。
然而,在微服务架构中,配置管理一般有以下需求
所以,对于微服务架构而言,一个通用的配置管理机制是必不可少的,常见做法是使用配置服务器管理配置。
不管你的微服务项目是否使用Spring Cloud,相对于Spring Cloud Config,Apollo都是更好的选择。
Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。
更多介绍,请到GitHub了解:https://github.com/ctripcorp/apollo。
本文的重点在于Apollo在客户端的使用,所以Apollo服务端使用的是官网提供的 Quick Start(针对本地测试使用)。如果要部署到生产环境,还请另行参考分布式部署指南。
1)Java
服务端要求1.8+,客户端要求1.7+。由于Quick Start会在本地同时启动服务端和客户端,所以需要在本地安装Java 1.8+。
2)MySQL
Apollo的表结构对timestamp
使用了多个default声明,所以需要5.6.5以上版本。
3)下载Quick Start安装包
官网为我们准备了 Quick Start 安装包。大家只需要下载到本地,就可以直接使用,免去了编译、打包过程。大家可以到github下载,也可以通过百度云盘下载。
1)创建数据库
Apollo服务端共需要两个数据库:ApolloPortalDB
和ApolloConfigDB
,我们把数据库、表的创建和样例数据都分别准备了sql文件,只需要导入数据库即可。
2)配置数据库连接信息
Apollo服务端需要知道如何连接到你前面创建的数据库,所以需要编辑deno.sh,修改ApolloPortalDB和ApolloConfigDB相关的数据库连接串信息。
**注意:填入的用户需要具备对ApolloPortalDB和ApolloConfigDB数据的读写权限。
#apollo config db info
apollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8
apollo_config_db_username=用户名
apollo_config_db_password=密码(如果没有密码,留空即可)
# apollo portal db info
apollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8
apollo_portal_db_username=用户名
apollo_portal_db_password=密码(如果没有密码,留空即可)
**注意:不要修改demo.sh的其它部分。
1)确保端口未被占用
Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用。
例如,在Linux/Mac下,可以通过如下命令检查
lsof -i:8080
在windows下,可以通过如下命令检查
netstat -aon|findstr "8080"
2)执行启动脚本
在Quick Start目录下执行如下命令
./demo.sh start
当看到如下输出后,就说明启动成功了!
==== starting service ====
Service logging file is ./service/apollo-service.log
Started [10768]
Waiting for config service startup.......
Config service started. You may visit http://localhost:8080 for service status now!
Waiting for admin service startup....
Admin service started
==== starting portal ====
Portal logging file is ./portal/apollo-portal.log
Started [10846]
Waiting for portal startup......
Portal started. You can visit http://localhost:8070 now!
3)异常排查
如果启动遇到了异常,可以分别查看service和portal目录下的log文件排查问题。
注:在启动apollo-configservice的过程中会在日志中输出eureka注册失败的信息,如com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
。需要注意的是,这个是预期的情况,因为apollo-configservice需要向Meta Server(它自己)注册服务,但是因为在启动过程中,自己还没起来,所以会报这个错。后面会进行重试的动作,所以等自己服务起来后就会注册正常了。
1)查看样例配置
1.1 打开http://localhost:8070
Quick Start集成了Spring Security简单认证,更多信息可以参考Portal 实现用户登录功能。
1.2 输入用户名apollo,密码admin后登录
配置中心中包含一个默认的项目SampleApp。
1.3 点击SampleApp进入配置界面,可以看到当前有一个配置timeout=100
如果提示系统出错,请重试或联系系统负责人
,请稍后几秒钟重试一下,因为通过Eureka注册的服务有一个刷新的延时。
2)新增项目配置
我们的客户端使用apollo需要新增相关的项目配置。
2.1 在首页点击创建项目
2.2 填写项目信息
点击提交,创建完成。
2.3 新增配置
点击新增配置
填写配置信息
点击提交, 此时配置还未生效。
2.4 发布配置
点击发布,配置立刻生效
2.5 回滚
如果配置做了修改之后,发现配置更改错误,这个时候可以使用回滚功能,回到上一个配置。
通过这些演示可以看出,Apollo的配置界面真的方便。
客户端使用Spring Boot 2.1.3搭建。新建一个项目,项目名称为apollo-client。
1)pom.xml文件添加Apollo客户端依赖
com.ctrip.framework.apollo
apollo-client
1.3.0
当前最新版本为1.3.0。此外,因为测试用到了Spring MVC,所以也需要引入starter-web的依赖。
2)application.yml添加配置信息
app:
# 应用ID(在Apollo服务端新增项目添加的应用ID)
id: test-app
apollo:
# apollo-config-service地址
meta: http://127.0.0.1:8080
3)启动类添加@EnableApolloConfig
注解
@SpringBootApplication
@EnableApolloConfig // 开启Apollo客户端
public class ApolloClientApplication {
public static void main(String[] args) {
SpringApplication.run(ApolloClientApplication.class, args);
}
}
4)新增一个测试接口
@RestController
public class TestController {
@RequestMapping("/index")
public String index() {
return "hello 2019!";
}
}
5)启动服务测试
在Apollo配置中心中,我们对该项目有一条配置server.port = 8088(后来改为9088)。
启动服务,访问http://localhost:9088/index
,返回hello 2019!
。证明,客户端是从服务端获取的配置。
也可以从控制台输出看到:Tomcat started on port(s): 9088 (http) with context path ''。
1)Spring Placeholder的使用
Spring应用通常会使用Placeholder来注入配置,使用的格式形如${someKey:someDefaultValue},如${timeout:100}。冒号前面的是key,冒号后面的是默认值(建议在实际使用时尽量给出默认值,以免由于key没有定义导致运行时错误)。Apollo从v0.10.0开始的版本支持placeholder在运行时自动更新。如果需要关闭placeholder在运行时自动更新功能,可以通过以下两种方式关闭
1.1 Java Config使用方式
新建配置类JavaConfigBean
如下
/**
* Java Config方式
*
* @author z_hh
* @time 2019年2月24日
*/
@Configuration
public class JavaConfigBean {
@Value("${timeout:20}")
private int timeout;
public int getTimeout() {
return timeout;
}
}
新增访问端点
// 1.Java Config方式
@Autowired
JavaConfigBean javaConfigBean;
@RequestMapping("/index1")
public String index1() {
return "timeout:" + javaConfigBean.getTimeout();
}
浏览器访问http://127.0.0.1:9088/index1
,正确返回配置的值
1.2 ConfigurationProperties使用方式
Spring Boot提供了@ConfigurationProperties
把配置注入到bean对象中。Apollo也支持这种方式。
新增配置类SampleRedisConfig
/**
* ConfigurationProperties使用方式
*
* @author z_hh
* @time 2019年2月24日
*/
@Configuration
@ConfigurationProperties(prefix = "redis.cache")
public class SampleRedisConfig {
private int expireSeconds;
private int commandTimeout;
public void setExpireSeconds(int expireSeconds) {
this.expireSeconds = expireSeconds;
}
public void setCommandTimeout(int commandTimeout) {
this.commandTimeout = commandTimeout;
}
public int getExpireSeconds() {
return expireSeconds;
}
public int getCommandTimeout() {
return commandTimeout;
}
}
新增访问端点
// 2. ConfigurationProperties使用方式
@Autowired
SampleRedisConfig sampleRedisConfig;
@RequestMapping("/index2")
public String index2() {
return sampleRedisConfig.getCommandTimeout() + "--" + sampleRedisConfig.getExpireSeconds();
}
浏览器访问http://127.0.0.1:9088/index2
,正确返回配置的值
2)Spring Annotation的支持
Apollo同时还增加了几个新的Annotation来简化在Spring环境中的使用。
@ApolloConfig
用来自动注入Config对象@ApolloConfigChangeListener
用来自动注册ConfigChangeListener@ApolloJsonValue
用来把配置的json字符串自动注入为对象2.1 @ApolloConfig
的使用
新增访问端点
// 3. @ApolloConfig使用
@ApolloConfig
private Config config;
@RequestMapping("/index3")
public String index3() {
Set propertyNames = config.getPropertyNames();
propertyNames.forEach(key -> {
System.err.println(key + "=" + config.getIntProperty(key, 0));
});
return propertyNames.toString();
}
浏览器访问http://127.0.0.1:9088/index3
,控制台正确打印配置的值
2.2 @ApolloConfigChangeListener
的使用
@ApolloConfigChangeListener
private void someOnChange(ConfigChangeEvent changeEvent) {
// update injected value of batch if it is changed in Apollo
if (changeEvent.isChanged("timeout")) {
System.out.println(config.getIntProperty("timeout", 0));
}
}
在Apollo服务端修改timeout
配置的值为300
,发布后,控制台打印300。
2.3 @ApolloJsonValue
的使用
新增用户类
/**
* 用户
*
* @author z_hh
* @time 2019年2月24日
*/
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
服务端新增配置:jsonBeanProperty=[ { "username": "john", "password": "1234" }, { "username": "simon", "password": "222132" } ]。
客户端获取配置
// 4. @ApolloJsonValue使用
@ApolloJsonValue("${jsonBeanProperty:[]}")
private List anotherJsonBeans;
@RequestMapping("/index4")
public void hello4() {
anotherJsonBeans.forEach(item -> {
System.err.println(item.getUsername() + "--" + item.getPassword());
});
}
浏览器访问http://127.0.0.1:9088/index4
,控制台正确打印配置的值
参考博客:https://blog.csdn.net/aaronsimon/article/details/83657612