服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心

一般项目来说我们通常把相关配置放在单独的配置文件中,文件后缀用properties或者yml的格式。但是每当我们修改配置文件,服务必须重启,否则无法生效。如果是一个分布式项目,配置文件很多的话,这样就不太高效。Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git。

项目实战


创建一个仓库,并在仓库下创建一个文件夹用来存放配置,创建如下三个配置文件。

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_02


配置server端创建一个子模块config,引入如下依赖


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_03

配置文件配置git仓库,填写上自已的账户和密码


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_04

Spring Cloud Config也提供本地存储配置的方式。我们只需要设置属性spring.profiles.active=native,config server会默认从应用的src/main/resource目录下检索配置文件。也可以通过spring.cloud.config.server.native.searchLocations=file:E:/properties/属性来指定配置文件的位置。启动类添加如下注解,并访问如下配置文件


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_05

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_06


配置client端新建子模块config-client模块,并引入如下依赖


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_07

        配置文件

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_08

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_09

spring.application.name:对应{application}部分

spring.cloud.config.profile:对应{profile}部分

spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用

spring.cloud.config.uri:配置中心的具体地址

spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。

注意:与spring cloud相关属性配置必须配置在bootstrapo.yml,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties。

       启动类无需添加注解,然后编写一个测试方法看是否能正确获取配置文件的参数。

服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_10

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_11

如图客户端成功拿到了配置参数。接下去我们修改配置文件,并push到git服务器,我们测试一下看客户端是否能及时更新。


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_12

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_13

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_14

服务端更新了,但是客户端没有更新。因为spring boot只有在启动时才会去获取配置信息。只有重启模块,才能获取到更新的配置信息。

开启更新机制在客户端子模块,引入

spring-boot-starter-actuator来实现refresh机制。

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_15

对需要刷新的类加上注解@RefreshScope,当配置更改时,标有该注解的bean就得到特殊处理来生效配置。我们修改配置文件并push到git服务器,然后以post请求访问http://localhost:8089/

act uator /refresh

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_16

这时候访问接口添加@RefreshScope类获取更新后的配置,未加的类获取配置仍是旧的。


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_17

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_18

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_19

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_20

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_21


使用webhook监听配置更新


WebHook是当某个事件发生时,通过发送http post请求的方式来通知信息接收方。Webhook来监测你在Github.com上的各种事件,最常见的莫过于push事件。如果你设置了一个监测push事件的Webhook,那么每当你的这个项目有了任何提交,这个Webhook都会被触发,这时Github就会发送一个HTTP POST请求到你配置好的地址。

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_22


消息总线机制如果项目少配置少可以通过/refresh来手动刷新配置,如果项目复杂的情况,这种方式就不适用了,spring cloud bus消息总线可以解决修改的真正动态刷新。为了实现配置中心服务器和实现高可用,降低服务端和客户端的耦合度,进行如下改造。服务端添加如下依赖:


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_23

配置文件新增如图配置


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_24

启动类添加如下注解


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_25

客户端改造,添加和服务端一样的依赖,然后修改配置文件


服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_26

spring.cloud.config.discovery.enabled :开启Config服务发现支持

spring.cloud.config.discovery.serviceId:指定server端的name,也就是server端spring.application.name的值

删除 spring.cloud.config.uri

       客户端启动类也加上注解,然后启动服务中心和这俩个子模块。

服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_27

如果要达成高可用,把config的配置文件改个端口,然后再开一个运行实例,就有一个服务端集群为客户端提供服务了。


接下去通过消息总线Spring Cloud Bus更新客户端配置文件。

Spring cloud bus的核心思想是通过分布式的启动器对spring boot应用进行扩展,也可以用来建立一个多个应用之间的通信频道。目前唯一实现的方式是用AMQP消息代理作为通道,同样特性的设置(有些取决于通道的设置)在更多通道的文档中。其实本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有Kafka和RabbitMQ。

实现架构图如下:

服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_28

流程如下:


  1. push配置触发post请求给Bus/refresh
  2. server端接到更新请求并发送spring cloud bus
  3. spring cloud bus接收到消息并通知给客户端
  4. 客户端接收到通知,请求server端获取最新配置
  5. 所有客户端均获取到最新的配置信息

安装kafka的具体步骤可以查看zookeeper和kafka环境搭建这篇文章。

      config服务模块新增如下依赖

服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_29

        配置文件:

服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_30

config-client客户端模块新增如下依赖


服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_31

配置文件


服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_32

运行这俩个模块模块和服务中心,因为spring cloud bus依赖kafka,别忘记启动kafka,接的我们在服务中心就会看到服务端和客户端的注册信息。


服务配置的入口service类型为nodePort 服务端配置信息失败_springcloud配置中心_33

查看服务端的配置文件


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_34

查看客户端获取的配置内容


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_35

修改配置文件并push到git服务器


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_36

  再次访问服务端的配置文件,文件已更新


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_37

 我们发送post请求去更新,如果想实现动态更新,可以集成wenhooks实现动态更新,看上面,配置地址:http://localhost:8088/actuator/bus-refresh


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_38

客户端再去获取配置,就能获取到最新的配置信息。


服务配置的入口service类型为nodePort 服务端配置信息失败_配置文件_39

如果想知道spring cloud bus时间传播的细节,可以通过跟踪总线事件(RemoteApplicationEvent的子类都是总线事件),访问如图地址:


服务配置的入口service类型为nodePort 服务端配置信息失败_frps server端配置_40