Spring Boot 2.0 整合携程Apollo配置中心

原文:https://www.jianshu.com/p/23d695af7e80javascript

 

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,可以集中化管理应用不一样环境、不一样集群的配置,配置修改后可以实时推送到应用端,而且具有规范的权限、流程治理等特性,适用于微服务配置管理场景。css

服务端基于Spring Boot和Spring Cloud开发,打包后能够直接运行,不须要额外安装Tomcat等应用容器。java

Java客户端不依赖任何框架,可以运行于全部Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。mysql

.Net客户端不依赖任何框架,可以运行于全部.Net运行时环境。git

若是想要深刻了解,能够到github上参见Apollo配置中心,官网的介绍很详细。本章主要讲述Spring Boot 2.0 整合Apollo配置中心。github

1、Apollo配置中心服务端(来源于官网)

本文的重点在于Apollo在客户端的使用,因此Apollo服务端使用的是官网提供的 Quick Start(针对本地测试使用),后续文章会专门讲述Apollo服务端在分布式环境下的部署。redis

1.1 准备工做

  1. Java
    Apollo服务端要求Java 1.8+,客户端要求Java 1.7+,笔者本地使用的是Java 1.8。
  2. MySQL
    Apollo的表结构对timestamp使用了多个default声明,因此须要5.6.5以上版本。笔者本地使用的是8.0.13版本
  3. 下载 Quick Start
    官网为咱们准备了 Quick Start 安装包。你们只须要下载到本地,就能够直接使用,免去了编译、打包过程。你们能够到github下载,也能够经过百度云盘下载

1.2 安装步骤

1.2.1 建立数据库

Apollo服务端共须要两个数据库:ApolloPortalDB和ApolloConfigDB,官网把数据库、表的建立和样例数据都分别准备了sql文件(在下载的 Quick Start 安装包的sql目录下),只须要导入数据库便可。sql

1.2.1.1 建立ApolloPortalDB

经过各类Mysql客户端(Navicat,DataGrip等)导入sql/apolloportaldb.sql便可
下面以MySQL原生客户端为例:数据库

source /your_local_path/sql/apolloportaldb.sql 

导入成功后,能够经过执行如下sql语句来验证:json

select `Id`, `AppId`, `Name` from ApolloPortalDB.App; 
Id AppId Name
1 SampleApp Sample App
1.2.1.2 建立ApolloConfigDB

经过各类Mysql客户端(Navicat,DataGrip等)导入sql/apolloconfigdb.sql便可
下面以MySQL原生客户端为例:

source /your_local_path/sql/apolloconfigdb.sql 

导入成功后,能够经过执行如下sql语句来验证:

select `NamespaceId`, `Key`, `Value`, `Comment` from ApolloConfigDB.Item; 
NamespaceId Key Value Comment
1 timeout 100 sample timeout配置

1.2.2 配置数据库链接信息

Apollo服务端须要知道如何链接到你前面建立的数据库,因此须要编辑demo.sh,修改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=密码(若是没有密码,留空便可) 

1.3 启动Apollo配置中心

1.3.1 确保端口未被占用

Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用。例如,在Linux/Mac下,能够经过以下命令检查:

lsof -i:8080 

在windows下,能够经过以下命令检查:

netstat -aon|findstr "8080" 

1.3.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! 

1.3.3 异常排查

若是启动遇到了异常,能够分别查看service和portal目录下的log文件排查问题。

注: 在启动apollo-configservice的过程当中会在日志中输出eureka注册失败的信息,如com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused。须要注意的是,这个是预期的状况,由于apollo-configservice须要向Meta Server(它本身)注册服务,可是由于在启动过程当中,本身还没起来,因此会报这个错。后面会进行重试的动做,因此等本身服务起来后就会注册正常了。

1.4 使用Apollo配置中心

1.4.1 查看样例配置

  1. 浏览器访问http://localhost:8070
    登陆界面
    登陆界面

    Quick Start集成了Spring Security简单认证,更多信息能够参考Portal 实现用户登陆功能
  2. 输入用户名apollo,密码admin登陆
    项目界面
    项目界面

    配置中心中包含一个默认的项目SampleApp
  3. 点击SampleApp进入配置界面,能够看到当前有一个配置timeout=100


    项目配置详情
    项目配置详情

    若是提示系统出错,请重试或联系系统负责人,请稍后几秒钟重试一下,由于经过Eureka注册的服务有一个刷新的延时。

1.4.2 新增项目配置

咱们的客户端使用apollo须要新增相关的项目配置。

  1. 点击新建项目


    项目信息
    项目信息
    • 应用ID:这个ID是应用的惟一标识
    • 应用名称:应用的名称,会展现在配置中心的首页上

    点击提交,建立完成


    应用配置界面
    应用配置界面
  2. 新增配置信息

     

    点击新增配置,填写配置信息
    配置信息
    配置信息
    点击提交,此时配置还未生效。
    未发布的配置
    未发布的配置
  3. 发布配置
    点击发布,配置马上生效


    生效的配置
    生效的配置
  4. 回滚
    若是配置作了修改以后,发现配置更改错误,这个时候可使用回滚功能,回到上一个配置


    回滚配置
    回滚配置

2、Apollo配置中心客户端

咱们客户端基于Spring Boot 2.0搭建,开发工具是InteIIij IDEA。新建一个项目,项目名称为apollo-client

2.1 客户端搭建

  1. 添加Apollo客户端依赖
    <dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</artifactId> <version>1.1.1</version> </dependency> 
    目前最新版本为1.1.1
  2. 添加配置信息
    # 应用ID(在Apollo服务端新增项目添加的应用ID) app.id=testclient # apollo-configservice地址 apollo.meta=http://127.0.0.1:8080 
  3. 开启Apollo客户端
    在项目的启动类上添加@EnableApolloConfig注解
  4. 新增一个测试接口
@RequestMapping("/index") public String hello(){ return "hello man"; } 
  1. 启动服务测试
    在Apollo配置中心中,咱们对该项目有一条配置server.port = 9000,启动服务,访问http://localhost:9000/index,返回hello man。证实,客户端是从服务端获取的配置。

2.2 客户端用法

在上一节,咱们简单的搭建了客户端,成功的使用服务端配置。Apollo为咱们提供的使用方式有不少种,下面只介绍Spring Boot 2.0环境下的使用方式。

2.2.1 Spring Placeholder的使用

Spring应用一般会使用Placeholder来注入配置,使用的格式形如${someKey:someDefaultValue},如${timeout:100}。冒号前面的是key,冒号后面的是默认值(建议在实际使用时尽可能给出默认值,以避免因为key没有定义致使运行时错误)。Apollo从v0.10.0开始的版本支持placeholder在运行时自动更新。若是须要关闭placeholder在运行时自动更新功能,能够经过如下两种方式关闭:

  1. 经过设置System Property apollo.autoUpdateInjectedSpringProperties,如启动时传入-Dapollo.autoUpdateInjectedSpringProperties=false
  2. 经过设置META-INF/app.properties中的apollo.autoUpdateInjectedSpringProperties=false
2.2.1.1 Java Config使用方式
  1. 新建配置类JavaConfigBean以下:
    /** * Java Config方式 * * @author simon * @create 2018-11-02 15:00 **/ @Configuration public class JavaConfigBean { @Value("${timeout:20}") private int timeout; public int getTimeout() { return timeout; } } 
  2. 新增访问端点
    //1.Java Config方式 @Autowired JavaConfigBean javaConfigBean; @RequestMapping("/index1") public String hello1(){ return javaConfigBean.getTimeout()+""; } 
  3. 测试
    浏览器访问http://127.0.0.1:8080/index1,正确返回配置的值
2.2.1.2 ConfigurationProperties使用方式

Spring Boot提供了@ConfigurationProperties把配置注入到bean对象中。Apollo也支持这种方式,下面的例子会把redis.cache.expireSecondsredis.cache.commandTimeout分别注入到SampleRedisConfigexpireSecondscommandTimeout字段中。

  1. 新增配置类SampleRedisConfig以下:
    /** * ConfigurationProperties使用方式 * * @author simon * @create 2018-11-02 9:30 **/ @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. 新增访问端点
    //2. ConfigurationProperties使用方式 @Autowired SampleRedisConfig sampleRedisConfig; @RequestMapping("/index2") public String hello2(){ return sampleRedisConfig.getCommandTimeout()+"--"+sampleRedisConfig.getExpireSeconds(); } 
  3. 测试
    浏览器访问http://127.0.0.1:8080/index2,正确返回配置的值

注: @ConfigurationProperties若是须要在Apollo配置变化时自动更新注入的值,须要配合使用EnvironmentChangeEventRefreshScope。这个我会在后续文章中详细描述。

2.2.2 Spring Annotation支持

Apollo同时还增长了几个新的Annotation来简化在Spring环境中的使用。

  • @ApolloConfig用来自动注入Config对象
  • @ApolloConfigChangeListener用来自动注册ConfigChangeListener
  • @ApolloJsonValue用来把配置的json字符串自动注入为对象
2.2.2.1 @ApolloConfig的使用
  1. 新增访问端点
    // 3. @ApolloConfig使用 @ApolloConfig private Config config; @RequestMapping("/index3") public String hello3(){ Set <String> propertyNames = config.getPropertyNames(); propertyNames.forEach(key -> { System.err.println(key+"="+config.getIntProperty(key,0)); }); return propertyNames.toString(); } 
  2. 测试
    浏览器访问http://127.0.0.1:8080/index3,正确打印配置的值
    redis.cache.commandTimeout=3000
    redis.cache.expireSeconds=20
    server.port=800
    timeout=200
2.2.2.2 @ApolloConfigChangeListener的使用
  1. 新增如下代码
    @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)); } } 
  2. 测试
    在Apollo服务端修改timeout配置的值为300,发布后,控制台打印300
2.2.2.3 @ApolloJsonValue的使用
  1. 新增User以下:
    /** * 用户 * * @author simon * @create 2018-11-02 16:41 **/ 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; } } 
  2. 服务端新增配置
    jsonBeanProperty=[ { "username": "john", "password": "1234" }, { "username": "simon", "password": "222132" } ]
  3. 客户端获取配置
    //4. @ApolloJsonValue使用 @ApolloJsonValue("${jsonBeanProperty:[]}") private List<User> anotherJsonBeans; @RequestMapping("/index4") public void hello4(){ anotherJsonBeans.forEach(item -> { System.err.println(item.getUsername()+"--"+item.getPassword()); }); } 
  4. 测试
    浏览器访问http://127.0.0.1:8080/index4,正确打印配置的值

源码下载 

相关文章
相关标签/搜索