通过前面几节,已经能够实现调用和负载和网关分发。但是如果有100个微服务时候呢?配置文件怎么管理,每个微服务重新打包运行吗?显然太笨了,而且还需要停机维护。怎么能够集中统一的管理每个服务的配置呢?最好还可以热部署,不停机就能更新最新配置。下面讲如何使用Spring cloud Config进行集中管理配置文件,以及Spring Bus更新配置(下节讲)。
Spring cloud config介绍和基本框架
在分布式系统中,每一个功能模块都能拆分成一个独立的服务,一次请求的完成,可能会调用很多个服务协调来完成,为了方便服务配置文件统一管理,更易于部署、维护,所以就需要分布式配置中心组件了,在spring cloud中,有分布式配置中心组件spring cloud config,它支持配置文件放在在配置服务的内存中,也支持放在远程Git仓库里。引入spring cloud config后,我们的外部配置文件就可以集中放置在一个git仓库里,再新建一个config server,用来管理所有的配置文件,维护的时候需要更改配置时,只需要在本地更改后,推送到远程仓库,所有的服务实例都可以通过config server来获取配置文件,这时每个服务实例就相当于配置服务的客户端config client。基本框架是有client和server
准备工作:在GitHub或者码云上建一个仓库,把配置文件传上去,比如我测试的是:
payServer-dev.properties和payServer-pro.properties 内容如下(部分内容带dev是为了区别):
spring.application.name=payServer-dev
server.port=9001
name=-dev
age=18
第一步:创建一个新项目ConfigServer,添加相关依赖,springboot版本是1.4.3.RELEASE
<!--引入Eureka_Server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!--引入Config-Server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!--加入监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引入spring cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
第二步、配置application文件
#ConfigServer
server.port=8086
##把服务注册到服务中心
eureka.client.serviceUrl.defaultZone=http://localhost:8899/eureka/
spring.application.name=ConfigServer
#服务的git仓库地址,注意不是.git 结尾的
spring.cloud.config.server.git.uri=https://gitee.com/vsalw/SpringConfig/
#强制从远程GIT仓库拉取数据到本地
spring.cloud.config.server.git.force-pull=true
#配置文件所在的目录
spring.cloud.config.server.git.search-paths=/**
#配置文件所在的分支 默认master
spring.cloud.config.label=master
#git仓库的用户名 注意此处不是spring.cloud.config.username
spring.cloud.config.server.git.username=你的用户名
#git仓库的密码
spring.cloud.config.server.git.password=你的密码
第三步、在启动类加@EnableConfigServer和@EnableDiscoveryClient注解。
常见坑:
1、此时当你访问http://127.0.0.1:8086/payServer/pro 时候就会返回一下信息:
说明server端配置正常,但是有人或许会问,你为什么访问http://127.0.0.1:8086/payServer/pro这个地址。没有看到controller写啊。实际上这个是有固定映射的。在准备工作时候我上传了payServer-dev.properties和payServer-pro.properties 这2个文件,经常写配置的同学会发现这是2个环境的配置文件一个是dev一个是pro,这里的项目名称就是payServer.后面的-dev实际是表示适用于某种环境。具体映射关系如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中application就是payServer ,profile就是后面的后缀dev和pro,label是指分支,默认mater. 当访问http://127.0.0.1:8086/payServer/pro会去payServer-pro.properties 找,并返回。这个application也是后面client里面需要指定的,当客户端来获取配置文件的时候需要告诉服务端他要哪个服务的配置,这个服务的名称就是application对应的名称,此处就是payServer
2、关于Could not fetch remote for master remote,原因是不能合并分支,很多人说是本地仓库脏了,需要强制拉取,这个是一个原因,但是不能合并还有一种情况:用户名密码和仓库信息对吗,如果这些不对,也不能合并。其中仓库地址是http或者https开头的,不是.get结尾的。springcloud版本问题,配置也有区别,用户名密码配置如下,我就是踩了这个坑......
Camden.SR4和Camden.SR6的如下:
spring.cloud.config.server.git.username=your username
Edgware.SR2的如下:
spring.cloud.config.username=your username
3、一定细心,客户端和服务端引的依赖不一样,虽然长得像。
服务端是spring-cloud-config-server
客户端是 spring-cloud-starter-config
服务端已经配置好了,那么客户端如何去服务端获取配置呢?这里的客户端就是需要更新配置的服务,可以是AAA也可以是zuul,也可以是其他的,只要他需要动态更新配置文件,就可以理解是ConfigServer的客户端。下面新建一个客户端来演示
第四步、新建一个项目ConfigClient。版本同上。引入配置文件
<!--引入Config-Client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入Eureka_Server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- 引入spring cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
第五步、在resources目录新建一个配置文件bootstrap.properties 这个名称是固定的,后缀可以是properties或者yml,和application.properties在同一层级。具体这2个文件区别简单理解bootstrap比application的更早加载,优先级更高,属于引导启动。具体参考:https://www.cnblogs.com/BlogNetSpace/p/8469033.html
bootstrap.properties内容如下:
#注册到Eureka的地址
eureka.client.serviceUrl.defaultZone=http://localhost:8899/eureka/
#配置服务名称,就是Git上面的application,比如此处 payServer-dev.properties的application就是payServer
spring.application.name=payServer
#开启配置服务发现
spring.cloud.config.discovery.enabled=true
spring.cloud.config.failFast=true
#默认是master分支
#spring.cloud.config.label=master
#配置启用哪个配置文件
spring.cloud.config.profile=dev
第六步、在启动类加入@EnableDiscoveryClient注册到服务注册中心。
第七步、写一个测试的Controller,来测试从configServer获取到的name和age属性。
PropertiesController类
@RestController
public class PropertiesController {
@Value("${name}")
private String name;
@Value("${age}")
private String age;
@RequestMapping(value = "/properties")
public String pro() {
return "hello " + name + ",age:" + age;
}
}
到这里,开始看看效果,因为我们配置了把configServer和ConfigClient都注册到注册中心,所以我们要先启动Eureka,在启动configServer,最后启动configClient. 仔细观察configClent会发现打印一下日志:
而且端口是9001,但是我们项目没有配置端口哦。说明了是从configServer获取配置文件成功,使用的是准备工作时候payServer-dev的配置信息,至于为什么是dev而不是pro,是因为在bootstrap.properties指定了。访问测试的controller:
一切正常!至此,本节结束。有一个问题是配置是获取到了,当配置有更新的时候还是只能重启,重新拉取配置,如何不关机来获取配置呢,请看下一节。
源码下载:SpringCloudConfig