本文为《Spring Cloud微服务实战》一书的摘要总结
快速入门
构建配置中心
- 创建基础的Spring Boot工程,加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
-
在主类上添加
@EnableConfigServer
注解,开启Spring Cloud Config的服务端功能 -
添加配置信息
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/LiuRunzhi/springcloud_config/ # git仓库的位置
search-paths: spring_cloud_config #配置仓库路径下的相对搜索位置,可以配置多个
username: username #访问git仓库的用户名
password: password #访问git仓库的用户密码
server:
port: 7001
- 验证配置中心是否正常
我们在仓库中添加配置文件,如userserver.properties,userserver-dev.yml,userserver-prod,然后使用以下格式访问配置中心:
-
/{application}-{profile}.yml
http://localhost:7001/userserver-dev.yml
-
/{application}-{profile}.properties
http://localhost:7001/userserver-dev.properties
我们在Git仓库中添加一个config-label-test分支,并向该分支提交配置,然后可以使用下面的格式访问:
-
/{application}/{profile}/{label}
http://localhost:7001/userserver/dev/config-label-test
-
/{lable}/{application}-{profile}.yml
http://localhost:7001/config-label-test/userserver-test.yml
-
/{lable}/{application}-{profile}.properties
http://localhost:7001/config-label-test/userserver-dev.yml
不带文件后缀的访问方式将返回带有配置信息的JSON格式的数据,带文件后缀的访问方式将直接返回配置信息字符串。
通过上面的请求,配置中心通过Git在本地暂存了配置文件,可以有效的防止当Git仓库故障而引起无法加载配置信息的情况;如果出现这种情况,配置中心会返回本地暂存的配置信息。
客户端配置映射
- 在微服务应用中加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- 新建
bootstrap.yml
配置文件
spring:
application:
name: server_client
cloud:
config:
label: master
profile: test
uri: http://localhost:7001/
应用将会根据上面的配置向配置服务请求配置信息。
- 注入配置信息:
@Value("${msg}")
private String msg;
//或者是:
@Autowired
private Environment env;
public void test(){
System.out.println(env.getProperty("msg","undefined"));
}
服务端详解
基础架构
-
应用启动时,根据bootstrap.properties中配置的应用名{application}、环境名{profile},分支名{label}向配置中心请求获取配置信息。
-
配置中心 根据自己维护的Git仓库和客户端传来的配置定位信息去查找配置信息。
-
通过 git clone 命令将找到的配置信息下载到配置中心 的文件系统中。
-
配置中心 创建Spring的ApplicationContext实例,并从Git本地仓库中加载配置信息,最后将这些配置内容读取出来返回给客户端应用。
-
客户端应用在获取到外部配置文件后加载到客户端的ApplicationContext实例,Jar包内部重复的配置信息将会被外部配置信息覆盖。
Git 配置仓库
Git远程仓库地址我们还可以使用{application}、{profile},{label}占位符,如:
spring:
cloud:
config:
uri: http://localhost:7001/{application}
这样,当客户端想配置中心请求配置信息时,配置中心可以根据客户端的spring.application.name来填充{application}占位符。
另外当远程仓库的分支名包含’/'时,那么{label}参数在HTTP的URL中应该用"(_)" 来代替
配置多个仓库
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/LiuRunzhi/springcloud_config/
search-paths: spring_cloud_config
username: xxx
password: xxx
repos:
consumer:
pattern: consumer/*
uri: https://gitee.com/zhirun/springcloudconfig/
server:
port: 7001
上面的配置中,访问http://localhost:7001/consumer/test,将会去读请求https://gitee.com/zhirun/springcloudconfig/consumer-test.yml和https://gitee.com/zhirun/springcloudconfig/consumer-test.properties
安全保护
我们可以在配置中心加入Spring Security,以实现密码保护。
- 配置中心加入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 配置用户名和密码
spring:
security:
user:
name: user
password: 123456
- 在客户端中加入安全信息来通过校验:
spring:
cloud:
config:
username: user
password: 123456
加密解密
对称加密
如果使用的是Oracle JDK,那么需要下载JCE,并替换掉$JAVA_HOME/jre/lib/security目录下的local_policy.jar和US_export_policy.jar两个jar包,如果使用的OpenJDK,则不需要这一步。
我们需要在配置中心的bootstrap.yml配置文件中添加秘钥信息:
encrypt:
key: AnyStringYouWantOnlyIfTtsComplex
然后我们就可以通过/encrypt和/decrypt来加密和解密了,这两个请求都是post。如果我们使用了Spring Security,那么我们需要对这两个请求关闭csrf:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().mvcMatchers(HttpMethod.POST, "/encrypt/**","/decrypt/**").permitAll();
}
}
加密解密相关端点:
- /encrypt/status:查看加密功能状态
- /key:查看秘钥
- /encrypt:对请求的body内容加密
- /decrypt:队请求的body内容解密
在远程仓库的配置文件:
如果是yml配置文件:
msg: '{cipher}316d12b654c3731cff08ee8c36e26769d4e97d6caa7b78c85949105e5757675d84fdfd78413d9f17ffdb173ffc66c62d'
如果是properties文件(不需要单引号):
msg: {cipher316d12b654c3731cff08ee8c36e26769d4e97d6caa7b78c85949105e5757675d84fdfd78413d9f17ffdb173ffc66c62d
非对称加密
使用JDK自带的keytool生成秘钥:
然后在配置中心的bootstrap.yml配置文件中配置:
encrypt:
key-store:
location: file:///e:\config-server.keystore #如果秘钥在classpath路径下,直接指定秘钥名就可了,即config-server.keystore
alias: config-server
password: 123456 #秘钥库口令
secret: 123456 #不能胡乱设置,因为我在生成密钥时并没有让我输入秘钥口令,只输入了秘钥库口令,所以秘钥口令应该是跟秘钥库口令是一致的,我猜测这里应该设置秘钥口令
服务化配置中心
-
配置中心和客户端都加入eureka依赖
-
配置中心和客户端的主类都添加
@EnableDiscoveryClient
注解 -
配置中心的application.yml配置文件中指定服务注册中心,客户单应用在bootstrap.yml中指定注册中心
-
客户端bootstrap.yml做如下配置:
spring:
application:
name: server_client
cloud:
config:
profile: test
discovery:
enabled: true #开启通过服务来访问配置中心
service-id: CONFIG-SERVER #配置中心注册的服务名称
eureka:
client:
service-url:
defaultZone: http://192.168.1.6:1111/eureka
instance:
prefer-ip-address: true
动态刷新配置
我们只需要在客户端加入actuator依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后暴露/refresh端口:
management:
endpoints:
web:
exposure:
include: refresh
当远程仓库的配置发生变化后,我们可以以Post方式请求客户端的/actuator/refresh端口,这样客户端ApplicationContext中的配置信息就重新获取与刷新了。