SpringBoot2.x整合携程Apollo配置中心

参考博客:https://blog.csdn.net/aaronsimon/article/details/83657612

一、背景

对于传统的单体应用,通常使用配置文件管理所有配置。比如Spring Boot开发的单体应用,配置内容可以放在application.yml文件,需要切换环境的话可以设置多个Profile并在启动应用时指定spring.pfofiles.active={profile}。

然而,在微服务架构中,配置管理一般有以下需求

  • 集中管理配置:一个使用微服务架构的应用系统可能会包含成千上万个微服务,因此集中管理配置是非常有必要的。
  • 不同环境不同配置:例如,数据源配置在不同的环境(开发、测试、预发布、生产等)中是不同的。
  • 运行期间可动态调整:例如,可根据各个微服务的负载情况,动态调整数据源连接池大小或熔断阈值,并且在调整配置时不停止微服务。
  • 配置修改后可自动更新。如配置内容发生变化,微服务能够自动更新配置。

所以,对于微服务架构而言,一个通用的配置管理机制是必不可少的,常见做法是使用配置服务器管理配置。

不管你的微服务项目是否使用Spring Cloud,相对于Spring Cloud Config,Apollo都是更好的选择。

SpringBoot2.x整合携程Apollo配置中心_第1张图片

二、Apollo简介

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

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

Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。

更多介绍,请到GitHub了解:https://github.com/ctripcorp/apollo。

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

本文的重点在于Apollo在客户端的使用,所以Apollo服务端使用的是官网提供的 Quick Start(针对本地测试使用)。如果要部署到生产环境,还请另行参考分布式部署指南。

1、准备工作

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下载,也可以通过百度云盘下载。

2、安装步骤

1)创建数据库

Apollo服务端共需要两个数据库:ApolloPortalDBApolloConfigDB,我们把数据库、表的创建和样例数据都分别准备了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的其它部分。

3、启动Apollo配置中心

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(它自己)注册服务,但是因为在启动过程中,自己还没起来,所以会报这个错。后面会进行重试的动作,所以等自己服务起来后就会注册正常了。

4、使用Apollo配置中心

1)查看样例配置

1.1 打开http://localhost:8070

SpringBoot2.x整合携程Apollo配置中心_第2张图片

Quick Start集成了Spring Security简单认证,更多信息可以参考Portal 实现用户登录功能。

1.2 输入用户名apollo,密码admin后登录

SpringBoot2.x整合携程Apollo配置中心_第3张图片

配置中心中包含一个默认的项目SampleApp。

1.3 点击SampleApp进入配置界面,可以看到当前有一个配置timeout=100

SpringBoot2.x整合携程Apollo配置中心_第4张图片

如果提示系统出错,请重试或联系系统负责人,请稍后几秒钟重试一下,因为通过Eureka注册的服务有一个刷新的延时。 

2)新增项目配置

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

2.1 在首页点击创建项目

SpringBoot2.x整合携程Apollo配置中心_第5张图片

2.2 填写项目信息

SpringBoot2.x整合携程Apollo配置中心_第6张图片

  • 应用ID:这个ID是应用的唯一标识
  • 应用名称:应用的名称,会展示在配置中心的首页上

点击提交,创建完成。

2.3 新增配置

点击新增配置

SpringBoot2.x整合携程Apollo配置中心_第7张图片

填写配置信息

SpringBoot2.x整合携程Apollo配置中心_第8张图片

点击提交, 此时配置还未生效。

SpringBoot2.x整合携程Apollo配置中心_第9张图片

2.4  发布配置

点击发布,配置立刻生效

SpringBoot2.x整合携程Apollo配置中心_第10张图片

SpringBoot2.x整合携程Apollo配置中心_第11张图片

SpringBoot2.x整合携程Apollo配置中心_第12张图片

2.5 回滚

如果配置做了修改之后,发现配置更改错误,这个时候可以使用回滚功能,回到上一个配置。

SpringBoot2.x整合携程Apollo配置中心_第13张图片

SpringBoot2.x整合携程Apollo配置中心_第14张图片

 

SpringBoot2.x整合携程Apollo配置中心_第15张图片

通过这些演示可以看出,Apollo的配置界面真的方便。 

四、Apollo配置中心客户端

1、客户端搭建

客户端使用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 ''。

2、客户端用法

1)Spring Placeholder的使用

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

  • 通过设置System Property apollo.autoUpdateInjectedSpringProperties,如启动时传入-Dapollo.autoUpdateInjectedSpringProperties=false
  • 通过设置META-INF/app.properties中的apollo.autoUpdateInjectedSpringProperties=false

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

你可能感兴趣的:(分布式微服务,中间件)