一、常规的配置设置方式
- Hardcode:写死在代码之中,每次修改需要发布修改代码,并且配置零散的存放在程序各处
- 配置文件:从代码中提到application.yml和bootstrap.yml文件中,虽然修改后依旧要重新发布程序,但是配置被集中管理了
- 环境变量:一般情况下是通过程序启动参数 和 系统层面的环境变量实现
- 数据库(缓存)存储:将参数存放到数据库中使用,这种方式会增加数据库的压力
1、传统配置管理的缺点
- 格式不统一:传统的配置文件格式不统一,SpringBoot的有properties和yml,spring的用xml配置,再老一点的还有使用json的
- 没有版本管理:使用配置文件还有git和svn能管理一下,存到数据库中的 真的是改掉再也变不回来了。
- 基于静态配置:修改、发布的流程繁琐,每次变动都需要在发布
- 分布零散:hardcode方式直接散落在代码中,配置文件的方式好一点,但是随之时代的进步,在分布式的架构中配置文件的方式力不从心了,每一个模块都有大量的配置
二、分布式配置中心——Config
Config作为SpringCloud官方指定产品,必然有独到之处,在配置管理方面主要提供了三大功能
- 统一配置:提供了一个中心化的配置方案,将各个项目中的配置内容集中在Config Server一端
- 环境隔离:Config Server提供了多种环境隔离机制,Client可以根据自身所处的项目环境(比如生产环境、测试环境)加载对应的配置文件
- 动态刷新:支持运行期改变配置属性
除此之外,还有加密解密、定向推送等功能
1、Config的配置文件命名规则
- application:服务的名字
- profile:环境名称
- label:对应git上不同的分支,默认为:master(程序的git版本与之对应,可以用于配置文件的版本控制)
规则1:{application}-{profile}.yml或{application}-{profile}.properties
示例:order-dev.yml 订单服务开发环境的配置文件
规则2:/{label}/{application}-{profile}.yml或/{label}/{application}-{profile}.properties
示例:/master/order-dev.yml 主分支下的订单服务开发环境的配置文件
规则3:{application}/{profile}[/{label}]
2、config小demo
(1)前期准备
1)创建一个git项目
在git、码云或者github上创建一个新的项目,专门用来存放配置文件,我这里命名为:config-repo
2)在git上创建配置文件
在config-repo中创建一个文件名为config-consumer-dev.yml
info:
profile: dev
name: Saul
words: 'God bless me'
然后提交文件,再创建一个配置文件,文件名为config-consumer-prod.yml
info:
profile: prod
name: Paul
words: 'God bless you'
(2)服务端代码
1)创建一个config-server(配置中心的服务模块)模块,修改配置文件
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
2)修改配置文件
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication{
public static void main(String[] args){
new SpringApplicationBuilder(ConfigServerApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
3)创建配置文件application.yml
server:
port: 60000
spring:
application:
name: config-server
cloud:
config:
server:
#强制重载配置,把远端上的配置覆盖掉
overrides:
#忽略远端上的test属性,使用这里的test值
test: mytest
git:
#git地址
uri: https://github.com/xxxx/config-repo.git
#git登录名
username: 敲代码的旺财
#git密码
password: 真帅
#配置文件在git下的目录,可以配置多个,主要用于区分开项目
#search-paths: test, mall
#强制拉取
force-pull: true
4)运行模块进行测试
发送一个git请求到 http://localhost:60000/config-consumer/dev
- http://localhost:60000/:这部分是服务地址
- config-consumer/dev:这部分是配置的文件名
可以多尝试几种访问:config会自动转换格式,返回我们对应的格式
- http://localhost:60000/config-consumer-dev.yml
- http://localhost:60000/config-consumer/dev.properties
- http://localhost:60000/config-consumer/dev.json
(3)客户端代码
1)创建一个config-client模块,修改配置文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- 配置中心需要他暴露端口,提供动态拉取参数的能力 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-starter-actuator</artifactId>
</dependency>
</dependencies>
2)修改配置文件
@SpringBootApplication
public class ConfigClientApplication{
public static void main(String[] args){
new SpringApplicationBuilder(ConfigClientApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
3)创建一个Controller
@RestController
//spring的注解,可以重新初始化当前对象,并且会完全的重新注入对象
@RefreshScope
public class Controller{
@Value("${name}")
public String name;
@Value("${myWords}")
public String words;
@GetMapping("/name")
public String getName(){
return name;
}
@GetMapping("/words")
public String getWords(){
return words;
}
}
4)创建配置文件application.yml
server:
port: 61000
#从配置中心获取words属性
myWords: ${words}
spring:
application:
name: config-client
cloud:
config:
#配置中心地址
uri: http://localhost:60000
#加载的配置文件的环境(这里一般不是写死的 而是通过启动参数,或者系统环境变量来配置)
profile: prod
label: master
#指定配置文件中的application,默认的为spring.application.name的值
name: config-consumer
#开放端口用于刷新配置文件
management:
security:
#关闭安全访问
enabled: false
endpoints:
web:
exposure:
#开放所有端口
include: "*"
endpoint:
helth:
show-details: always
5)启动程序,调用controller进行测试
- get请求访问地址
http://localhost:61000/name - 然后改变配置文件,把name属性改掉
name: Saul and Paul
- get请求调用刷新配置的端口
http://localhost:61000/actuator/refresh - 再次访问地址
http://localhost:61000/name
三、高可用配置中心
1、实现原理
现在的配置中心是单节点的,所有的服务都连接在这个单节点的配置中心上,如果配置中心宕机了,那所有服务的配置就不能更新了,我们将配置中心搭建成集群,在服务和配置中心集群中间,搭建一个负载均衡器,如果一个配置中心的节点宕机了,负载均衡器将请求转到还存活的节点上
2、借助Eureka实现高可用配置中心
(1)服务端代码修改
1)创建一个config-server(配置中心的服务模块)模块,修改配置文件
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
2)修改配置文件
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication{
public static void main(String[] args){
new SpringApplicationBuilder(ConfigServerApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
3)创建配置文件application.yml
server:
port: 60000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:20000/eureka/
spring:
application:
name: config-server
cloud:
config:
server:
git:
#git地址
uri: https://github.com/xxxx/config-repo.git
#git登录名
username: 敲代码的旺财
#git密码
password: 真帅
#配置文件在git下的目录,可以配置多个,主要用于区分开项目
#search-paths: test, mall
#强制拉取
force-pull: true
这里可以启动多个config-server,改下端口号就行了
(2)客户端代码修改
1)创建一个config-client模块,修改配置文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- 配置中心需要他暴露端口,提供动态拉取参数的能力 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
2)修改启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigClientApplication{
public static void main(String[] args){
new SpringApplicationBuilder(ConfigClientApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
4)创建配置文件application.yml
server:
port: 61000
#从配置中心获取words属性
myWords: ${words}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:20000/eureka/
spring:
application:
name: config-client
cloud:
config:
discovery:
#启动服务发现功能
enabled: true
service-id: config-server-eureka
#加载的配置文件的环境(这里一般不是写死的 而是通过启动参数,或者系统环境变量来配置)
profile: prod
label: master
#指定配置文件中的application,默认的为spring.application.name的值
name: config-consumer
#开放端口用于刷新配置文件
management:
security:
#关闭安全访问
enabled: false
endpoints:
web:
exposure:
#开放所有端口
include: "*"
endpoint:
helth:
show-details: always
四、配置加密
数据库密码是一个相当机密的信息,尽量不要让安全级别不高的个人或团队直接接触到。尽管我们程序猿们个个都是信得过的,不会随便登录生产环境做破坏性操作,可也不能保证突发事件的发生。比如今天我和产品经理干了一架,打输了,气不过,拿着密码登录生产环境删库跑路了。
我们需要引入一个数据安全机制,减少敏感数据的暴露程度,因此需要对三个环节做严格控制。
数据加密端 就像颁发CA证书一样,必须由一个中心机构用密钥对明文进行加密。这里也一样,需要在生产环境中创建一个特定的服务,专门做加密操作。最重要的是,加密所用的秘钥只能保存在那台机器里,不能对外暴露数据存放端 数据存放端(如GitHub)只能保存加密过后的数据数据解密端 由于密钥都保存在数据加密端,因此数据解密和数据加密必须放在同一个地方进行,加密数据在传给客户端之前要经过解密,不能将秘钥下放到客户端机器上进行解密。
我们需要引入一个数据安全机制,减少敏感数据的暴露程度,因此需要对三个环节做严格控制
- 数据加密端:就像颁发CA证书一样,必须由一个中心机构用密钥对明文进行加密。这里也一样,需要在生产环境中创建一个特定的服务,专门做加密操作。最重要的是,加密所用的秘钥只能保存在那台机器里,不能对外暴露
- 数据存放端:数据存放端(如GitHub)只能保存加密过后的数据
- 数据解密端:由于密钥都保存在数据加密端,因此数据解密和数据加密必须放在同一个地方进行,加密数据在传给客户端之前要经过解密,不能将秘钥下放到客户端机器上进行解密
1、加密Demo
(1)修改jdk的jce主键
- 在Oracle的官网下载jce
https://www.oracle.com/java/technologies/javase-jce-all-downloads.html
只有jdk6/7/8并且版本低于6u16/7u171/8u161,才需要下载 - 下载的文件解压,得到loacl_policy.jar和US_export_policy.jar,将解压后的文件拷贝到
java目录\jre\lib\security下,覆盖同名文件
(2)config-server修改bootstrap.yml配置文件
encrypt:
#加密用的key,随便写
key: keyboardDog
发送一个get无参请求到localhost:60001/encrypt/status上,测试配置是否成功
(3)对字符串进行加密/解密
- 加密
发送一个post请求到localhost:60001/encrypt上,使用row传参,参数直接填写想要加密的字符串 - 解密
发送一个post请求到localhost:60001/dencrypt上,使用row传参,参数直接填写加密过后的字符串
(4)修改github上的配置文件
info:
profile: prod
name: Paul
#这里把字符串换掉,{cipher} 表示这个字符串需要解密 ,后面跟上加密过后的字符串
words: '{cipher}xxxxxxxxxxxxxxxxxxxxx'
1120

被折叠的 条评论
为什么被折叠?



