往往,我们使用配置文件管理一些配置信息,比如application.yml
。
单体应用架构
,配置信息的管理、维护并不会显得特别麻烦,手动操作就可以,因为就一个工程;
微服务架构
,因为我们的分布式集群环境中可能有很多个微服务,我们不可能一个一个去修改配置然后 重启生效,在一定场景下我们还需要在运行期间动态调整配置信息,比如:根据各个微服务的负载情 况,动态调整数据源连接池大小,我们希望配置内容发生变化的时候,微服务可以自动更新。
场景总结如下:
那么,我们就需要对配置文件进行集中式管理
,这也是分布式配置中心的作用。
1、Config简介
Spring Cloud Config
是一个分布式配置管理方案,包含了 Server
端和 Client
端两个部分。
Server 端
:提供配置文件的存储、以接口的形式将配置文件的内容提供出去,通过使用 @EnableConfigServer
注解在 Spring boot
应用中非常简单的嵌入Client 端
:通过接口获取配置数据并初始化自己的应用2、Config分布式配置应用
说明:Config Server
是集中式的配置服务,用于集中管理应用程序各个环境下的配置。 默认使用Git
存
储配置文件内容,也可以SVN
。
比如,我们要对“简历微服务”的application.yml
进行管理(区分开发环境、测试环境、生产环境)
1)登录github
,创建项目riemann-config-repo
2)上传yml
配置文件,命名规则如下:
{application}-{profile}.yml
或者 {application}-{profile}.properties
其中,application
为应用名称,profile
指的是环境(用于区分开发环境,测试环境、生产环境等)
示例:riemann-service-resume-dev.yml、riemann-service-resume-test.yml、riemann-service-resume- prod.yml
3)构建Config Server统一配置中心
3、新建SpringBoot
工程
1)引入依赖坐标(需要注册自己到Eureka)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-integrationartifactId>
<groupId>com.riemanngroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>riemann-cloud-configserver-9006artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
dependencies>
project>
2)配置启动类,使用注解@EnableConfigServer
开启配置中心服务器功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer // 开启配置中心功能
public class ConfigServerApplication9006 {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication9006.class,args);
}
}
3)application.yml
配置
server:
port: 9006
# 注册到Eureka服务中心
eureka:
client:
service-url:
# 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
defaultZone: http://RiemannCloudEurekaServerA:8761/eureka,http://RiemannCloudEurekaServerB:8762/eureka
instance:
prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
# 实例名称: 192.168.1.103:riemann-service-resume:8080,我们可以自定义它
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
application:
name: riemann-cloud-configserver
cloud:
config:
server:
git:
uri: https://github.com/riemannChow/SpringCloudConfig #配置git服务地址
username: [email protected] # 配置git用户名
password: xxx # 配置git密码
search-paths:
- riemann-config-repo
# 读取分支
label: master
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
# 针对的被调用方微服务名称,不加就是全局生效
# riemann-service-resume:
# ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载策略调整
# springboot中暴露健康检查等断点接口
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接口的细节
endpoint:
health:
show-details: always
测试访问:http://localhost:9006/master/riemann-service-resume-dev.yml
,查看到配置文件内容
4)构建Client
客户端(在已有简历微服务基础上)
已有工程中添加依赖坐标
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-clientartifactId>
dependency>
application.yml
修改为bootstrap.yml
配置文件
bootstrap.yml
是系统级别的,优先级比application.yml
高,应用启动时会检查这个配置文件,在这个配置文件中指定配置中心的服务地址,会自动拉取所有应用配置并且启用。
(主要是把与统一配置中心连接的配置信息放到bootstrap.yml
)
注意:需要统一读取的配置信息,从集中配置中心获取。
bootstrap.yml
server:
port: 8080
spring:
application:
name: riemann-service-resume
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰命名转换为下划线命名
cloud:
# config客户端配置,和ConfigServer通信,并告知ConfigServer希望获取的配置信息在哪个文件中
config:
name: riemann-service-resume #配置文件名称
profile: dev #后缀名称
label: master #分支名称
uri: http://localhost:9006 #ConfigServer配置中心地址
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
#注册到Eureka服务中心
eureka:
client:
service-url:
# 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
defaultZone: http://RiemannCloudEurekaServerA:8761/eureka,http://RiemannCloudEurekaServerB:8762/eureka
instance:
prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
# 实例名称: 192.168.1.103:riemann-service-resume:8080,我们可以自定义它
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
# 自定义Eureka元数据
metadata-map:
cluster: cl1
region: rn1
# springboot中暴露健康检查等断点接口
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接口的细节
endpoint:
health:
show-details: always
不用重启微服务,只需要手动的做一些其他的操作(访问一个地址/refresh
)刷新,之后再访问即可。
此时,客户端取到了配置中心的值,但当我们修改GitHub
上面的值时,服务端(Config Server
)能实 时获取最新的值,但客户端(Config Client)
读的是缓存,无法实时获取最新值。Spring Cloud
已经为我们解决了这个问题,那就是客户端使用post
去触发refresh
,获取最新数据。
1)Client
客户端添加依赖springboot-starter-actuator
(已添加)
2)Client
客户端bootstrap.yml
中添加配置(暴露通信端点)
# springboot中暴露健康检查所有端点
management:
endpoints:
web:
exposure:
include: "*"
3)Client
客户端使用到配置信息的类上添加@RefreshScope
4)手动向Client
客户端发起POST请求,http://localhost:8080/actuator/refresh
,刷新配置信息
注意:手动刷新方式避免了服务重启(流程:Git改配置—>for循环脚本手动刷新每个微服务)
思考:可否使用广播机制,一次通知,处处生效,方便大范围配置刷新?
实现一次通知处处生效
在微服务架构中,我们可以结合消息总线(Bus
)实现分布式配置的自动更新(Spring Cloud Config+Spring Cloud Bus
)
1、消息总线Bus
所谓消息总线Bus
,即我们经常会使用MQ
消息代理构建一个共用的Topic
,通过这个Topic
连接各个微服 务实例,MQ
广播的消息会被所有在注册中心的微服务实例监听和消费。换言之就是通过一个主题连接各个微服务,打通脉络。
Spring Cloud Bus
(基于MQ
的,支持RabbitMq/Kafka
) 是Spring Cloud
中的消息总线方案,Spring Cloud Config + Spring Cloud Bus
结合可以实现配置信息的自动更新。
2、Spring Cloud Config+Spring Cloud Bus 实现自动刷新
MQ
消息代理,我们还选择使用RabbitMQ
,ConfigServer
和ConfigClient
都添加都消息总线的支持以及
与RabbitMq
的连接信息。
1)Config Server服务端添加消息总线支持
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
2)ConfigServer添加配置
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
3)微服务暴露端口
management:
endpoints:
web:
exposure:
include: "*"
4)重启各个服务,更改配置之后,向配置中心服务端发送post
请求
http://localhost:9003/actuator/bus-refresh
,各个客户端配置即可自动刷新
在广播模式下实现了一次请求,处处更新,如果我只想定向更新呢?
在发起刷新请求的时候http://localhost:9006/actuator/bus-refresh/riemann-service-resume:8081
,即为最后面跟上要定向刷新的实例的 服务名:端口号即可。