一般应用中都会有配置文件,即便是号称“零配置”的Spring Boot
应用,也无法完全做到不使用配置文件,因为配置文件是为了迎合软件的一些个性化需求,所以说应用程序是无法避免这种配置的,特别是在微服务系统架构中,应用程序往往会部署在多个实例上,每个实例都有各自的不同的配置,如果配置发生了更改,每个服务实例都需要进行配置的变更,既然配置的变更无法避免,每个微服务自己的配置文件散落在自己的应用中,必然会对应用的配置和升级带来挑战,故而需要引入集中化配置,来解决微服务中关于配置的问题。
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{lable}/{application}-{profile}.yml
/{application}-{profile}.properties
/{lable}/{application}-{profile}.properties
Spring Cloud Config
是Spring Cloud
团队创建的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分。
其中服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息、加密/解密信息等访问接口;而客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。
Spring Cloud Config
实现了对服务端和客户端中环境变量和属性配置的抽象映射,所以它除了适用于Spring
构建的应用程序之外,也可以在任何其他语言运行的应用程序中使用。由于Spring Cloud Config
实现的配置中心默认采用Git
来存储配置信息,所以使用Spring Cloud Config
构建的配置服务器,天然就支持对微服务应用配置信息的版本管理,并且可以通过Git
客户端工具来方便地管理和访问配置内容。当然它也提供了对其他存储方式的支持,比如SVN
仓库,本地化文件系统。
分布式外部化配置
Config Server
:管理应用程序的外部属性,底层实现基于Git
Config Client
Spring Cloud Config
服务端的基础架构:
Git
仓库:用来存储配置文件的地方。Config Server
:构建的分布式配置中心,config-server
工程,在该工程中指定了所要连接的Git
仓库位置以及账户、密码等连接信息。Git
仓库:在Config Server
的文件系统中,每次客户端请求获取配置信息时,Config Server
从Git
仓库中获取最新配置到本地,然后在本地Git
仓库中读取并返回。当远程仓库无法获取时,直接将本地内容返回。Service A
、Service B
:具体的微服务应用,它们指定了Config Server
的地址,从而实现从外部化获取应用自己要用的配置信息。这些应用在启动的时候,会向Config Server
请求获取配置信息来进行加载。客户端应用从配置管理中获取配置信息遵从下面的执行流程:
bootstrap.properties
中配置的应用名{application}
、环境名{profile}
、分支名{label}
,向Config Server
请求获取配置信息。Config Server
根据自己维护的Git
仓库信息和客户端传递过来的配置定位信息去查找配置信息。git clone
命令将找到的配置信息下载到Config Server
的文件系统中。Config Server
创建Spring
的ApplicationContext
实例,并从Git
本地仓库中加载配置文件,最后将这些配置内容读取出来返回给客户端应用。ApplicationContext
实例,该配置内容的优先级高于客户端Jar
包内部的配置内容,所以在Jar
包中重复的内容将不再被加载。Config Server
巧妙地通过git clone
将配置信息存于本地,起到了缓存的作用,即使当Git
服务端无法访问的时候,依然可以取Config Server
中的缓存内容进行使用。
JDK8+
Gradle4+
Spring Boot 2.0.0.M3
Spring Cloud Starter Netflix Eureka Client Finchley.M2
Spring Cloud Config Server Finchley.M2
以之前的micro-weather-eureka-client
为蓝本,创建micro-weather-config-server
项目
修改build.gradle
配置,添加Spring Cloud Config Server
依赖:
//buildscript代码块中脚本优先执行
buildscript {
//ext用于定义动态属性
ext {
springBootVersion = '2.0.0.M3'
}
//使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
repositories {
//mavenCentral()
maven{ url "https://repo.spring.io/snapshot" }
maven{ url "https://repo.spring.io/milestone" }
maven{ url "http://maven.aliyun.com/nexus/content/groups/public/" }
}
//依赖关系
dependencies {
//classpath声明了在执行其余的脚本时,ClassLoader可以使用这些依赖项
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
//使用插件
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
//指定了生成的编译文件的版本,默认是打成了jar包
group = 'com.study.spring.cloud'
version = '1.0.0'
//指定编译.java文件的JDK版本
sourceCompatibility = 1.8
//使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
repositories {
//mavenCentral()
maven{ url "https://repo.spring.io/snapshot" }
maven{ url "https://repo.spring.io/milestone" }
maven{ url "http://maven.aliyun.com/nexus/content/groups/public/" }
}
ext {
springCloudVersion = 'Finchley.M2'
}
//依赖关系
dependencies {
//Eureka Client
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
//Spring Cloud Config Server
compile('org.springframework.cloud:spring-cloud-config-server')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
//Spring Cloud依赖管理
dependencyManagement{
imports{
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
修改com.study.spring.cloud.weather
包下的Application
类,加入@EnableConfigServer
注解:
package com.study.spring.cloud.weather;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
/*
* @SpringBootApplication注解声明Spring Boot应用
* 作用等同于@Configuration, @EnableAutoConfiguration, @ComponentScan,
* 简化Spring配置
*/
@SpringBootApplication
//启用可发现的客户端
@EnableDiscoveryClient
//启用Config Server
@EnableConfigServer
//Application类一定要处于整个工程的根目录下,这样它才能根据配置去扫描子节点下的Spring的Bean
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
修改application.properties
配置文件:
#应用名称
spring.application.name=micro-weather-config-server
#指定端口
server.port=8888
#注册服务器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#GitHub仓库
spring.cloud.config.server.git.uri=https://github.com/yehongliu/config-server-study.git
#下级目录
spring.cloud.config.server.git.search-paths=config-repo
先运行micro-weather-eureka-server
,再运行micro-weather-config-server
,运行结果如下:
访问http://localhost:8888/auther/dev
页面:
JDK8+
Gradle4+
Spring Boot 2.0.0.M3
Spring Cloud Starter Netflix Eureka Client Finchley.M2
Spring Cloud Config Client Finchley.M2
以之前的micro-weather-eureka-client
为蓝本,创建micro-weather-config-client
项目
修改build.gradle
配置,添加Spring Cloud Config Client
依赖:
//依赖关系
dependencies {
//Eureka Client
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
//Spring Cloud Config Client
compile('org.springframework.cloud:spring-cloud-config-client')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
修改application.properties
配置文件:
#应用名称
spring.application.name=micro-weather-config-client
#注册服务器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#指定环境
spring.cloud.config.profile=dev
#指向Config Server
spring.cloud.config.uri=http://localhost:8888/
修改test
下的com.study.spring.cloud.weather
包下的ApplicationTests
类:
package com.study.spring.cloud.weather;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
@Value("${auther}")
private String auther;
@Test
public void contextLoads() {
assertEquals("willow51",auther);
}
}
先运行micro-weather-eureka-server
和micro-weather-config-server
,再运行ApplicationTests
类的contextLoads
测试方法,运行结果如下: