0.简介

前面的文章我们创建了很多微服务,每个微服务都需要自己的配置才能运行,每个服务都有自己配置文件,微服务多了配置文件就多了,如果要修改某一个参数,就需要修改多个微服务的配置文件。为了解决这个问题,Spring Cloud提供了一个解决方案就是使用spring cloud config分布式配置中心来做到一处修改,处处运行。

整个流程可以分成三大步骤:

(1)首先搭建一个远程仓库(github、gitlab、码云都行,本文使用码云做演示),然后创建一个项目,命名为spring-cloud-config (名称无所谓),然后把这个仓库克隆到本地。

(2)然后搭建配置中心的服务端

(3)最后搭建配置中心的客户端

官方文档:https://docs.spring.io/spring-cloud-config/docs/current/reference/html/

(注:后面可以用nacos代替,nacos=spring cloud eureka+spring cloud config + spring cloud bus)

1.搭建远程仓库

我们打开码云,创建一个仓库。

注意,仓库最好设置成公开,如果设置成私有,下面的配置信息需要加上仓库的用户名和密码。

然后把仓库克隆到本地,然后我们创建一个测试文件,里面放置一个简单文件如下:

config:
  info: "hello,config!"

并命名为:config-test.yml。然后把这个文件上传到到码云上。

这样git仓库部分就搭建完毕了,后期可以往仓库里添加其他配置文件了。

注意: 统一配置中心服务端 config Server 读取远程仓储的配置的时候是有一定的规则,因此在远程仓储中的配置文件命名也要有一定的规则。

远程仓库配置文件命名规则:

{application}-{profile}.yml/{application}-{profile}.properties

config server 读取远程仓库的配置规则:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

其中,label代表的是分支,profile代表的是环境。

2.搭建配置服务中心服务端

我们参考前面的文章, 创建一个module,

POM文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<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>s-cloud</artifactId>
        <groupId>site.longkui</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>s-cloud-config</artifactId>


    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 添加统一服务配置中心 config-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>3.1.8</version>
        </dependency>
        <!--eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>3.1.8-SNAPSHOT</version>
        </dependency>

    </dependencies>
</project>

配置文件application.yml参考如下(这里增加了git的配置):

server:
  port: 20000  #服务的端口
#spring相关配置
spring:
  application:
    name: service-config  #服务的名称
  cloud:
    config:
      server:
        git:
          #  username: xxxxx
          #  password: xxxxx
          skip-ssl-validation: true  #跳过ssl认证
          uri: https://gitee.com/guo1635/spring-cloud-config.git #要读取的远程仓库的配置文件的地址。
          default-label: master # 指定分支,不指定则默认master

#eureka配置
eureka:
  client:
    service-url:
      # 填写注册中心服务器地址
      defaultZone: http://localhost:7001/eureka
    # 是否需要将自己注册到注册中心
    register-with-eureka: true
    # 是否需要搜索服务信息
    fetch-registry: true
  instance:
    # 使用ip地址注册到注册中心
    prefer-ip-address: true
    # 注册中心列表中显示的状态参数
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

创建启动类参考如下,注意,这里加入了@EnableConfigServer 注解,表示spring-cloud-config的服务端

package site.longkui.scloudconfig;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient//  eureka 客户端
@EnableConfigServer//  config 服务端
public class sCloudConfig {
    public static void main(String[] args) {
        SpringApplication.run(sCloudConfig.class, args);
    }
}

然后我们访问我们的测试文件的地址:

http://localhost:20000/master/config-test.yml

可以看到,正常获取我们创建的测试配置文件。我们修改码云上的配置文件后,刷新后也可以得到最新的配置信息。

3.搭建配置服务中心客户端

客户端的POM文件参考如下:

<?xml version="1.0" encoding="UTF-8"?>
<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>s-cloud</artifactId>
        <groupId>site.longkui</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>s-cloud-config-clinent</artifactId>

    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- config -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>3.1.8</version>
        </dependency>
        <!--eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>3.1.8-SNAPSHOT</version>
        </dependency>
        <!-- 新版本的springcloud不支持bootstrap.yml,需要引入下面的依赖       -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.7</version>
        </dependency>
    </dependencies>

</project>

新建配置文件,bootstrap.yml,详细原因可以看:https://www.longkui.site/program/java/application-bootstrap/5060/

简单来说就是bootstrap.yml的优先级比application.yml优先级高。

server:
  port: 30000  #服务的端口
#spring相关配置
spring:
  application:
    name: service-config-client  #服务的名称
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: test #读取后缀名称
      uri: http://127.0.0.1:20000 #配置中心地址


#eureka配置
eureka:
  client:
    service-url:
      # 填写注册中心服务器地址
      defaultZone: http://localhost:7001/eureka
    # 是否需要将自己注册到注册中心
    register-with-eureka: true
    # 是否需要搜索服务信息
    fetch-registry: true
  instance:
    # 使用ip地址注册到注册中心
    prefer-ip-address: true
    # 注册中心列表中显示的状态参数
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

我们配置测试配置文件config-test.yml,这里的name对应的是文件名的前面部分,profile对应的是后面部分。

注意,上面这里用的IP地址+端口的方式进行的访问,实际操作中,更多的是用服务的方式进行访问,参考如下:

server:
  port: 30000  #服务的端口
#spring相关配置
spring:
  application:
    name: service-config-client  #服务的名称
  cloud:
    #Config客户端配置
    config:
      discovery:
        service-id: service-config  #告诉当前客户端 统一配置中心的服务端服务id
        enabled: true #开启客户端,根据服务id到注册中心获取配置信息
      label: master #分支名称
      name: config #配置文件名称
      profile: test #读取后缀名称
#      uri: http://127.0.0.1:20000 #配置中心地址


#eureka配置
eureka:
  client:
    service-url:
      # 填写注册中心服务器地址
      defaultZone: http://localhost:7001/eureka
    # 是否需要将自己注册到注册中心
    register-with-eureka: true
    # 是否需要搜索服务信息
    fetch-registry: true
  instance:
    # 使用ip地址注册到注册中心
    prefer-ip-address: true
    # 注册中心列表中显示的状态参数
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

创建启动类:

package site.longkui.scloudconfigclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


@SpringBootApplication
@EnableEurekaClient//  eureka 客户端
public class sCloudConfigClient {
    public static void main(String[] args) {
        SpringApplication.run(sCloudConfigClient.class, args);
    }
}

创建controller

package site.longkui.scloudconfigclient.controller;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/config")
public class ConfigClientController {

    @Value("${config.info}")
    private String info;

    @GetMapping("/getConfig")
    public String getConfig(){
        return info;
    }

}

然后启动模块,访问我们的接口,可以看到,能够正确读取配置内容。

4.客户端手动刷新

客户端需要动态刷新的原因,请看下图:

我们修改了配置,不能立即在客户端生效,需要重新启动才能生效。

我们可以通过手动刷新和自动刷新来解决这个问题。

我们在客户端添加一个依赖

 <!-- 动态感知配置变化-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

对外暴露服务端点,让客户端可以接受到配置的更新,我们修改客户端的bootstrap.yml

#暴露服务端点,让客户端能感受到配置的更新
management:
  endpoints:
    web:
      exposure:
        include: "*"

然后在controller中加入@RefeshScope

package site.longkui.scloudconfigclient.controller;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigClientController {

    @Value("${config.info}")
    private String info;

    @GetMapping("/getConfig")
    public String getConfig(){
        return info;
    }

}

然后重启模块,此时修改配置后,需要在CMD中访问以下地址。

curl -X POST "http://127.0.0.1:30000/actuator/refresh

然后再访问客户端就可以手动刷新了。

自动刷新将在下一篇bus消息总线进行介绍。