文章目录
分布式配置中心应用场景
往往,使⽤配置⽂件管理⼀些配置信息,⽐如application.yml单体应⽤架构,配置信息的管理、维护并不会显得特别麻烦,⼿动操作就可以,因为就⼀个⼯程;
微服务架构,因为我们的分布式集群环境中可能有很多个微服务,我们不可能⼀个⼀个去修改配置然后重启⽣效,在⼀定场景下我们还需要在运⾏期间动态调整配置信息,⽐如:根据各个微服务的负载情况,动态调整数据源连接池⼤⼩,我们希望配置内容发⽣变化的时候,微服务可以⾃动更新。
场景总结如下:
-
集中配置管理,⼀个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的(⼀次修改、到处⽣效)
-
不同环境不同配置,⽐如数据源配置在不同环境(开发dev,测试test,⽣产prod)中是不同的
-
运⾏期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池⼤⼩等配置修改后可⾃动更新
-
如配置内容发⽣变化,微服务可以⾃动更新配置那么,我们就需要对配置⽂件进⾏集中式管理,这也是分布式配置中⼼的作⽤。
Spring Cloud Config
Config简介
Spring Cloud Config是⼀个分布式配置管理⽅案,包含了 Server端和 Client端两个部分。
-
Server 端:提供配置⽂件的存储、以接⼝的形式将配置⽂件的内容提供出去,通过使⽤
@EnableConfigServer
注解在 Spring boot 应⽤中⾮常简单的嵌⼊ -
Client 端:通过接⼝获取配置数据并初始化⾃⼰的应⽤
Config分布式配置应用
构建config服务端
说明:Config Server是集中式的配置服务,用于集中管理应用程序各个环境下的配置。 默认使用Git存储配置文件内容,也可以SVN。
⽐如,我们要对“简历微服务”的application.yml进⾏管理(区分开发环境、测试环境、⽣产环境)
- 登录码云,创建项⽬cloud-config-repo
- 上传yml配置⽂件,命名规则如下:
{application}-{profile}.yml 或者 {application}-{profile}.properties其中,application为应⽤名称,profile指的是环境(⽤于区分开发环境,测试环境、⽣产环境等)
示例:cloud-service-resume-dev.yml、cloud-service-resume-test.yml、cloud-service-resume-prod.yml
-
构建Config Server统⼀配置中心
基于上一篇文章的工程基础上创建子工程cloud-config-server9006 -
引入pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
- 主启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigServer9006 {
public static void main(String[] args) {
SpringApplication.run(ConfigServer9006.class, args);
}
}
- yaml配置文件
server:
port: 9006
eureka:
client:
service-url:
defaultZone: http://eureka8762.com:8762/eureka/,http://eureka8761.com:8761/eureka/ # 入驻的服务注册中心地址
register-with-eureka: true
instance:
#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)
prefer-ip-address: true
#自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
application:
name: cloud-service-config
cloud:
config:
server:
git:
uri: ################# #配置git服务地址
username: ############## #配置git用户名
password: ########### #配置git密码
search-paths:
- cloud-service-resume
# 读取分支
label: master
#针对的被调用方微服务名称,不加就是全局生效
#lagou-service-resume:
# ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载策略调整
# springboot中暴露健康检查等断点接口
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
测试访问:http://localhost:9006/master/cloud-service-resume-dev.yml,查看到配置⽂件内容
构建config客户端
- 修改原有的resume服务pom文件,新增依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
- application.yml修改为bootstrap.yml配置⽂件
bootstrap.yml是系统级别的,优先级⽐application.yml⾼,应⽤启动时会检查这个配置⽂件,在这个配置⽂件中指定配置中⼼的服务地址,会⾃动拉取所有应⽤配置并且启⽤。(主要是把与统⼀配置中⼼连接的配置信息放到bootstrap.yml)
注意:需要统⼀读取的配置信息,从集中配置中心获取
server:
port: 8080
spring:
application:
name: cloud-service-resume
datasource:
url: jdbc:mysql://192.168.137.144:3306/lagou?useUnicode=true&characterEncoding=utf8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
jpa:
database: mysql
show-sql: true
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
cloud:
config:
uri: http://localhost:9006/
name: cloud-service-resume
label: master
profile: dev
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
# 单机版
#defaultZone: http://localhost:8761/eureka # 入驻的服务注册中心地址
# 集群版
defaultZone: http://eureka8762.com:8762/eureka/,http://eureka8761.com:8761/eureka/ # 入驻的服务注册中心地址
instance:
#使⽤ip注册,否则会使⽤主机名注册了(此处考虑到对⽼版本的兼容,新版本经过实验都是ip)
prefer-ip-address: true
#⾃定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:@project.version@
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
- 添加controller
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${config.info}")
private String configInfo;
@RequestMapping("/version")
public String getInfo() {
return configInfo;
}
}
- 测试
Config配置手动刷新
不⽤重启微服务,只需要⼿动的做⼀些其他的操作(访问⼀个地址/refresh)刷新,之后再访问即可
此时,客户端取到了配置中⼼的值,但当我们修改GitHub上⾯的值时,服务端(Config Server)能实时获取最新的值,但客户端(Config Client)读的是缓存,⽆法实时获取最新值。Spring Cloud已经为我们解决了这个问题,那就是客户端使⽤post去触发refresh,获取最新数据。
-
Client客户端添加依赖springboot-starter-actuator(已添加)
-
Client客户端bootstrap.yml中添加配置(暴露通信端点)
management:
endpoints:
web:
exposure:
include: refresh
management:
endpoints:
web:
exposure:
include: "*"
- Client客户端使⽤到配置信息的类上添加@RefreshScope
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${config.info}")
private String configInfo;
@RequestMapping("/version")
public String getInfo() {
return configInfo;
}
}
- ⼿动向Client客户端发起POST请求,http://localhost:8080/actuator/refresh,刷新配置信息
刷新前请求
执行刷新
再次请求
注意:手动刷新方式避免了服务重启(流程:Git改配置—>for循环脚本手 动刷新每个微服务)
Config配置⾃动更新
实现⼀次通知处处⽣效
做分布式配置,可以采用zk(存储+通知),zk中数据变更,可以通知各个监听的客户端,客户端收到通知之后可以做出相应的操作(内存级别的数据直接⽣效,对于数据库连接信息、连接池等信息变化更新的,那么会在通知逻辑中进⾏处理,⽐如重新初始化连接池)
在微服务架构中,可以结合消息总线(Bus)实现分布式配置的⾃动更新(Spring Cloud Config+Spring Cloud Bus)
消息总线Bus
所谓消息总线Bus,即我们经常会使⽤MQ消息代理构建⼀个共⽤的Topic,通过这个Topic连接各个微服务实例,MQ⼴播的消息会被所有在注册中⼼的微服务实例监听和消费。换⾔之就是通过⼀个主题连接各个微服务,打通脉络。
Spring Cloud Bus(基于MQ的,⽀持RabbitMq/Kafka) 是Spring Cloud中的消息总线⽅案,Spring Cloud Config + Spring Cloud Bus 结合可以实现配置信息的⾃动更新。
Spring Cloud Config+Spring Cloud Bus 实现自动刷新
MQ消息代理,我们选择使⽤RabbitMQ,ConfigServer和ConfigClient都添加都消息总线的⽀持以及与RabbitMq的连接信息
- Config Server服务端添加消息总线⽀持
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
- ConfigServer添加配置
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
- 微服务暴露端⼝
management:
endpoints:
web:
exposure:
include: bus-refresh
#建议暴露所有的端⼝
management:
endpoints:
web:
exposure:
include: "*"
- 重启各个服务,更改配置之后,向配置中⼼服务端发送post请求 http://localhost:9006/actuator/bus-refresh,各个客户端配置即可⾃动刷新
刷新前
刷新后
- 定向刷新
在发起刷新请求的时候http://localhost:9006/actuator/bus-refresh/cloud-service-resume:8081
即为最后⾯跟上要定向刷新的实例的 服务名:端⼝号即可