将服务配置语服务代码分开
许多开发人员使用属性文件(yaml, json, properties,xml)存储他们的配置信息,这份配置文件存放在服务器上,通常包含数据库和中间件的连接信息,以及程序启动的元数据。
这种方法使用少量的应用程序,如果一个服务有上百个服务实例,当服务的配置文件需要改变时,就必须要应用程序重新编译,打包,发布,这样才能使新的配置文件生效。可想而知这个成本代价有多大,所以应该将服务的配置文件将代码分开,将配置文件进行统一的管理,当配置文件变化时,服务实例可以自动更新获取新的配置。
spring cloud config
我们将配置文件放入git或者svn等服务中,通过一个Config Server服务来获取git中的配置数据,而我们需要使用的到配置文件的Config Client系统可以通过Config Server来获取对应的配置。
Spring Cloud Config对这种需求提供了支持。
架构原理图如下:
- 首先我们需要一个远程的Git仓库,自己学习可以直接用GitHub,在在实际生产环境中,需要自己搭建一个Git服务器,远程Git仓库的作用主要是用来保存我们的配置文件
- 至于微服务则是我们具体的应用,这些应用在启动的时候会从Config Server中来加载相应的配置信息
- 当微服务尝试去从Config Server中加载配置信息的时候,Config Server会先通过git clone命令克隆一份配置文件保存到本地
- 由于配置文件是存储在Git仓库中,所以配置文件天然的具备版本管理功能,Git中的Hook功能可以实时监控配置文件的修改
搭建spring cloud config配置服务器
- 添加maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
- 在springboot入口类上添加
@EnableConfigServer
注解
/**
* config 引导类
* 注解@EnableConfigServer使服务成为spring cloud config服务
*
* @author hui.wang09
* @since 16 十月 2018
*/
@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
- 在
application
文件中配置Git仓库信息
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/wangfancying/spirng-config
search-paths: /
username: XXXX
password: *****
# uri表示配置中心所在仓库的位置
# search-paths表示仓库下的子目录
# username表示你的GitHub用户名
# password表示你的GitHub密码
应用程序的配置文件的命名规范是应用程序名-环境名称.yml
或者应用程序名-环境名称.properties
# 访问路径的写法也有多种方式:
/{application}/{profile}/[label]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
# 其中application表示配置文件的名字,
# profile表示环境,我们有dev、test、prod还有默认
# label表示分支,默认我们都是放在master分支上
这样我们就搭建好了spring cloud config 服务器了
config client 端使用spring cloud config
- 添加maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
-->
- 配置
bootstrap.yml
文件
spring:
cloud:
config:
uri: http://localhost:8081 #配置服务器的位置,不使用发现服务功能
name: spring-test-config #对应的配置服务中{application}
profile: dev #对应配置服务中的{profile}
label: master #对应的分支{label}
discovery:
enabled: true #启用发现服务功能
service-id: config-server #指定服务名称 这里指定的是config配置服务器的ID
. spring.cloud.config.name
对应config配置服务器中的{application}
. spring.cloud.config.profile
对应config配置服务器中的{profile}
. spring.cloud.config.label
对应config配置服务器中的{label}
. spring.cloud.config.url
对应config配置服务器的域名,在不使用复现服务的时候可以使用
这里的yml配置文件是:bootstrap.yml,它和application.yml文件一样,会被spring boot加载,但是bootstrap.yml会优先加载。
- 使用
@Value
读取配置文件
/**
* @author hui.wang09
* @since 16 十月 2018
*/
@RestController
@RefreshScope
public class ConfigController {
private final Logger logger = Logger.getLogger(ConfigController.class);
@Value("${name}")
private String name;
@RequestMapping("/hello")
public String hello() throws InterruptedException {
return "hello, " + name;
}
}
这个时候就完成了配置文件集中管理
关于配置的刷新
- config client端在启动类中配置
@RefreshScope
@SpringBootApplication
@RefreshScope
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
- 当配置更新时,可以访问http://<config client server>/refresh端点,就可以刷新服务端的配置文件了
敏感的配置信息
如果将敏感信息以纯文本的形式保存,是一种危险的行为,例如数据库连接、用户名、密码等。因此需要将一些敏感信息密文保存,只允许config client才能拿到明文,其他都拿不到明文
使用对称加密
- 配置服务器、config client端添加maven依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-rsa</artifactId>
</dependency>
- 配置spring cloud config配置服务器的bootstrap.yml
# 配置加密秘钥
encrypt:
key: test
配置完成后,可以访问http://<spring cloud config>/encrypt/status,返回{"status":"OK"}
表示配置成功
- 将需要加密的明文字符加密
post请求调用http://<spring cloud config>/encrypt 加密字符串
image.png
然后将加密的字符串配置到配置文件中(GitHub),加密属性前需要添加{cipher}
test = {cipher}14d32cc6fac775e9f8086636a7073d7d40b34eeb55a7b96337e8944433172667
- 配置spring cloud config 的application.yml文件,设置禁用服务器端属性解密,
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/wangfancying/spirng-config
search-paths: /**
username: XXXX
password: *****
#spring.cloud.config.server.encrypt.enabled设置是否禁用服务器端属性解密
encrypt:
enabled: false
spring.cloud.config.server.encrypt.enabled
设置是否禁用服务器端属性解密
- 配置config client端
spring:
cloud:
config:
name: spring-test-config # 和git里的文件名对应
discovery:
enabled: true
service-id: config-server
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8765/eureka
# 配置加密秘钥
encrypt:
key: test
配置秘钥encrypt.key
网友评论