文章目录
前言
Spring Cloud Config为分布式系统中的外部化配置提供服务器端和客户端支持。使用Config Server,您可以在中心位置管理所有环境中应用程序的外部属性。服务端获取或者配置各个客户端属性,客户端获取自己配置。
springCloud config可以结合git或者github的版本管理工具使用,满足了配置由于环境因素或者其他因素导致需要切换时,只需要修改git或者github上的配置信息即可,config自动刷新配置信息,并且推送到各个配置中心的客户端。
ps:这里提前补充一个知识点,作为config客户端的时候我们不再使用application.yml而是换做bootstrap.yml
bootstrap.yml(bootstrap.properties)用来在程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
bootstrap.yml 先于 application.yml 加载
并且在config中除了自身微服务的application,从git或者github上面获取到application开头的配置文件都将被其他微服务客户端所共享,而且优先级会高于各个微服务客户端指定配置在config的配置文件。
重点!!!
以下所有的学习都是config与git的结合使用,所以其中对于一些配置名称的解释仅针对与git。
一、config服务端
1.pom引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2.配置文件
application.yml
server:
port: 3344
spring:
application:
name: config-server
cloud:
config:
server:
git:
#github路径
uri: https://github.com/RomanticY/spring-cloud.git
#文件目录
search-paths:
- springcloud-config
#此处为github的登录名
username: ******
#此处为github的密码
password: ******
force-pull: true
#分支名称
label: sit
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
register-with-eureka: true
fetch-registry: true
下面是我github上面配置的文件
3.主启动
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigServerMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigServerMain3344.class,args);
}
}
4.测试
官网提供了访问外部配置文件的方式
其中我们使用第三种并且进行讲解,lable:对应的就是github的某个分支,application就是配置文件使用“-”分割之后的字段,例如我的github配置文件中的config-client(由于我的名称中间本身就带有“-”,所以此处就不再细分),profile就是分割之后剩下的部分,例如dev。
测试结果如下:
测试结果和我的github中的结果一样,测试通过。
二、客户端
1.pom引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2.配置文件
bootstrap.yml(替换application.yml)
server:
port: 3366
spring:
application:
name: config-client
cloud:
config:
#表明此为微服务获取的是github上的哪个分支配置文件
label: sit
#配置文件的名字的一部分
name: config-client
#配置文件的名字的一部分
profile: dev
#表名去哪里获取配置文件
uri: http://localhost:3344/
#其实config服务端会将远端所配置的文件在启动的时候读取到本地,客户端只需要配置config服务端的地址就可以访问了,以上的配置拼在一起就是http://localhost:3344/sit/config-client-dev.yml,说明此为微服务获取的是配置中心上的sit分支的config-client-dev.yml配置文件。
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
register-with-eureka: true
fetch-registry: true
3.主启动以及业务类
主启动
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigClientMain3366 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3366.class,args);
}
}
业务类
我们就获取一下配置文件中的config.spreak属性值
@RestController
@RequestMapping("/config")
public class configClientController {
@Value("${config.spreak}")
private String str;
@GetMapping("/getConfig")
private String getConfig(){
return str;
}
}
4.测试
获取成功,测试通过。
三、动态刷新
其实以上已经实现了config作为配置中心的最大作用之一,集中配置,但是如果不能做到客户端根据github上配置更新自己更新配置的话,在实际生产环境集群的环境下的话重启服务是大忌,就显得有些力不从心了。
下面演示config客户端的刷新,不需要重启微服务。
1.修改客户端配置文件
server:
port: 3366
spring:
application:
name: config-client
cloud:
config:
label: sit
name: config-client
profile: dev
uri: http://localhost:3344/
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
register-with-eureka: true
fetch-registry: true
management:
endpoints:
web:
exposure:
include: "*"
management.endpoints…暴露监控端点(此处需要引入actuator的依赖)
2.修改业务类
@RestController
@RequestMapping("/config")
@RefreshScope
public class configClientController {
@Value("${config.spreak}")
private String str;
@GetMapping("/getConfig")
private String getConfig(){
return str;
}
}
@RefreshScope刷新controller这个bean,重新加载配置信息。
3.测试
修改前,config客户端获取的信息为:
github修改为
向3366config客户端发送post:http://loacalhost:3366/actuator/refresh。用于刷新客户端配置信息
修改后。config客户端获取信息:
客户配置信息自动更新,无需重启服务,测试通过。
PS:在配置@RefreshScope注解在controller上时可能会导致拿到的配置信息的值为null,对此的解决办法就是,新建一个类,在这个类里面引入@RefreshScope和配置信息,然后将此类注入进spring,最后在controller中引用即可,此处贴出来我的修改后的代码。
ConfigValue
@Component
@RefreshScope
public class ConfigValue {
@Value("${config.spreak}")
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
ConfigClientController
@RestController
@RequestMapping("/config")
public class ConfigClientController {
@Autowired
private ConfigValue configValue;
@GetMapping("/getConfig")
private String getConfig(){
System.out.print("配置项:"+configValue.getStr());
return configValue.getStr();
}
}
以上操作中,又会带来一个新的问题,目前只解决了不需要重启服务了,但如果微服务过多的话,就需要每个微服务都要去发送给请求,这样的话就很麻烦。那么应该怎么办呢?
springcloud提供了一个组件叫做BUS(消息总线),它提供了一个共用的消息主题,并且让所有的微服务实例都连接,该主题中的所有消息都会被所有实例监听和消费,所以被称为消息总线。
那么,我们只需要让所有的微服务都订阅这个topic(主题),当微服务刷新数据的时候,将这个消息放置在topic中,那么其他微服务自动更新。
目前bus能结合MQ只有RabbitMQ和kafka。
目前在出差身边没有MQ,后面有机会把这一部分的学习知识补上。