Spring Cloud 十:配置中心介绍与使用

一,配置中心

为什么需要配置中心

单体应用,配置写在配置文件中,没有什么大问题。如果要切换环境 可以切换不同的profile(2种方式),但在微服务中,微服务比较多。成百上千,配置很多,需要集中管理,需要管理不同环境的配置,需要动态调整配置参数,更改配置不停服。

配置中心介绍

分布式配置中心包括3个部分:

  1. 存放配置的地方:git,svn ,数据库,本地文件 等。
  2. config server,从 1 读取配置。
  3. config client。是 config server 的客户端 消费配置。

注意:配置都不会自己更新,都是需要触发client才去git上拉取的。或者触发 在config-server上查看配置时,才去git上拉取。

二,使用

下面我们在Spring Boot 项目中集成 Spring Cloud Config,并以 github 作为配置存储,主要从以下两部分来演示:

  1. 脱离Eureka的配置中心搭建。
  2. 集成Eureka的配置中心搭建。

配置文件准备:

我们在github上面放以下四个配置文件:配置中心仓库地址

在这里插入图片描述

config-single-client-dev.yml

data:
  env: sinle-client-env
  user:
    username: bobo1
    password: 123

config-single-client-prod.yml

data:
  env: sinle-client-prod
  user:
    username: bobo2
    password: 1234

config-eureka-client-dev.yml

data:
  env: eureka-client-env
  user:
    username: bobo3
    password: 12345

config-eureka-client-prod.yml

data:
  env: eureka-client-prod
  user:
    username: bobo4
    password: 123456

1,脱离Eureka的配置中心搭建

最简单的配置中心,就是启动一个服务作为服务方,之后各个需要获取配置的服务作为客户端来这个服务方获取配置。

创建配置中心服务端

1,新建model,config-single-server,导入web和config-server依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

2,配置application.yml

server:
  port: 7001
spring:
  application:
    name: config-single-server
  cloud:
    config:
      server:
        git:
		  # 配置文件仓库地址
          uri: https://github.com/zhaosongbobo/spring-cloud-config-test
          username: github帐号
          password: github密码
		  # 配置文件主干
          default-label: master
		  # 跳过ssl检查
          skip-ssl-validation: true
		  # 配置文件保存的本地机器的目录
          basedir: /home/bobo/config

3,在启动类上面加@EnableConfigServer注解

@SpringBootApplication
@EnableConfigServer
public class ConfigSingleServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigSingleServerApplication.class, args);
    }

}

4,启动config-single-server验证

Spring Cloud Config 有它的一套访问规则,我们通过这套规则在浏览器上直接访问就可以。

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
  • {application} 就是应用名称,对应到配置文件上来,就是配置文件的spring.application.name值。
  • {profile} 就是配置文件的版本,我们的项目有开发版本、测试环境版本、生产环境版本,对应到配置文件上来就是以 application-{profile}.yml 加以区分,例如application-dev.yml、application-sit.yml、application-prod.yml。
  • {label} 表示 git 分支,默认是 master 分支,如果项目是以分支做区分也是可以的,那就可以通过不同的 label 来控制访问不同的配置文件了。

我们按照以上规则访问我们刚启动的服务端:

http://localhost:7001/config-single-client/dev/master

http://localhost:7001/config-single-client-dev.yml

http://localhost:7001/master/config-single-client-dev.yml

如下输出:

在这里插入图片描述

通过访问以上地址,如果可以正常返回数据,则说明配置中心服务端一切正常。

创建配置中心客户端

配置中心服务端好了,配置数据准备好了,接下来,就要在我们的项目中使用它了。

1,创建model,config-single-client,并导入web,config依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

2,配置bootstrap.yml和application.yml配置文件

bootstrap.yml

spring:
  application:
    name: config-single-client
  cloud:
    config:
      uri: http://localhost:7001
      profile: dev
      label: master
  profiles:
    active: dev

注意:这里为什么要用bootstrap配置文件?

这是由spring boot的加载属性文件的优先级决定的,你想要在加载属性之前去spring cloud config server上取配置文件,那spring cloud config相关配置就是需要最先加载的,而bootstrap.yaml的加载是先于application.yaml的,所以config client要配置config的相关配置就只能写到bootstrap.properties里了。

application.yml

server:
  port: 7008

3,读取配置文件内容,一般通过@Value 或 @ConfigurationProperties 来获取

@Component
@Data
public class GitConfig {
    @Value("${data.env}")
    private String env;
    @Value("${data.user.username}")
    private String username;
    @Value("${data.user.password}")
    private String password;
}
@Component
@Data
@ConfigurationProperties(prefix = "data")
public class GitAutoRefreshConfig {
    
    private String env;
    private UserInfo user;
    
    @Data
    public static class UserInfo {
        private String username;
        private String password;
    }
}

4,GitController来测试配置

@RestController
public class GitController {
    @Autowired
    private GitConfig gitConfig;

    @Autowired
    private GitAutoRefreshConfig gitAutoRefreshConfig;

    @GetMapping("/getInfo")
    public Object getInfo(){
        return gitConfig;
    }

    @GetMapping("/getAutoInfo")
    public Object getAutoInfo(){
        return gitAutoRefreshConfig;
    }
}

5,结果

在这里插入图片描述

在这里插入图片描述

2,集成Eureka的配置中心搭建

如果我们的系统中使用了 Eureka 作为服务注册发现中心,那么 Spring Cloud Config 也应该注册到 Eureka 之上,方便其他服务消费者使用,并且可以注册多个配置中心服务端,以实现高可用。

好的,接下来就来集成 Spring Cloud Config 到 Eureka 上。

创建Eureka服务端

1,新建model,eureka-server,配置pom依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

2,配置eureka,application.yml

spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url:
      defaultZone: http://euk-server1:8001/eureka/
  instance:
    hostname: euk-server1
server:
  port: 8001

3,启动类添加@EnableEurekaServer注解

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}
创建配置中心服务端并注册到EurekaServer

1,新建model,config-eureka-server,添加pom依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2,配置eureka和config application.yml

server:
  port: 8002
spring:
  application:
    name: config-eureka-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/zhaosongbobo/spring-cloud-config-test
          username: github帐号
          password: github密码
          default-label: master
          skip-ssl-validation: true
          basedir: /home/bobo/config

eureka:
  instance:
    hostname: euk-server2
  client:
    service-url:
      defaultZone: http://euk-server1:8001/eureka

3,启动类添加@EnableConfigServer和@EnableEurekaClient注解

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigEurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigEurekaServerApplication.class, args);
    }

}

4,启动config-eureka-sever,验证配置成功

在这里插入图片描述

创建配置中心客户端

客户端的配置相对来说变动大一点,加入了 Eureka 之后,就不用再直接和配置中心服务端打交道了,要通过 Eureka 来访问。另外,还是要注意客户端的 application 名称要和 github 中配置文件的名称一致。

1,新建model,config-eureka-client,添加pom依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2,配置bootstrap.yaml和application.yaml

bootstrap.yml

spring:
  application:
    name: config-eureka-client
  cloud:
    config:
      discovery:
        enabled: true
		# 指定配置中心服务端的server-id
        service-id: config-eureka-server
	  # 指定仓库主干
      label: master
	  # 指定版本
      profile: dev
eureka:
  client:
    service-url:
      defaultZone: http://euk-server1:8001/eureka/

application.yml

server:
  port: 8003

除了注册到 Eureka 的配置外,就是配置和配置中心服务端建立关系。

其中 service-id 也就是服务端的application name。

注意:这里为什么要用bootstrap配置文件?

这是由spring boot的加载属性文件的优先级决定的,你想要在加载属性之前去spring cloud config server上取配置文件,那spring cloud config相关配置就是需要最先加载的,而bootstrap.yaml的加载是先于application.yaml的,所以config client要配置config的相关配置就只能写到bootstrap.properties里了。

3,读取配置文件内容,一般通过@Value 或 @ConfigurationProperties 来获取

直接从上面例子拿过来,不用做更改:

@Component
@Data
public class GitConfig {
    @Value("${data.env}")
    private String env;
    @Value("${data.user.username}")
    private String username;
    @Value("${data.user.password}")
    private String password;
}
@Component
@Data
@ConfigurationProperties(prefix = "data")
public class GitAutoRefreshConfig {
    
    private String env;
    private UserInfo user;
    
    @Data
    public static class UserInfo {
        private String username;
        private String password;
    }
}

4,GitController来测试配置

@RestController
public class GitController {
    @Autowired
    private GitConfig gitConfig;

    @Autowired
    private GitAutoRefreshConfig gitAutoRefreshConfig;

    @GetMapping("/getInfo")
    public Object getInfo(){
        return gitConfig;
    }

    @GetMapping("/getAutoInfo")
    public Object getAutoInfo(){
        return gitAutoRefreshConfig;
    }
}

5,启动类

@SpringBootApplication
@EnableDiscoveryClient
public class ConfigEurekaClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigEurekaClientApplication.class, args);
    }

}

6,结果

在这里插入图片描述

三,手动刷新

Spring Cloud Config 在项目启动时加载配置内容这一机制,导致了它存在一个缺陷,修改配置文件内容后,不会自动刷新。例如我们上面的项目,当服务已经启动的时候,去修改 github 上的配置文件内容,这时候,再次刷新页面,对不起,还是旧的配置内容,新内容不会主动刷新过来。
但是,总不能每次修改了配置后重启服务吧。如果是那样的话,还是不要用它了为好,直接用本地配置文件岂不是更快。

它提供了一个刷新机制,但是需要我们主动触发。那就是 @RefreshScope 注解并结合 actuator ,注意要引入 spring-boot-starter-actuator 包。

1,在config-eureka-client的pom依赖中增加依赖actuator

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2,在 config client 端配置中增加 actuator 配置

application.yml

server:
  port: 8003
management:
  endpoint:
    shutdown:
      enabled: false
  endpoints:
    web:
      exposure:
        include: "*"

2、在需要读取配置的类上增加 @RefreshScope 注解,我们是 controller 中使用配置,所以加在 controller 中。

@RestController
@RefreshScope
public class GitController {
    @Autowired
    private GitConfig gitConfig;

    @Autowired
    private GitAutoRefreshConfig gitAutoRefreshConfig;

    @GetMapping("/getInfo")
    public Object getInfo(){
        return gitConfig;
    }

    @GetMapping("/getAutoInfo")
    public Object getAutoInfo(){
        return gitAutoRefreshConfig;
    }
}

注意,以上都是在 client 端做的修改。

之后,重启 client 端,重启后,我们修改 github 上的配置文件config-eureka-client-dev.yml

原:

data:
  env: eureka-client-env
  user:
    username: bobo3
    password: 12345

修改后:

data:
  env: eureka-client-env
  user:
    username: bobo3修改111
    password: 12345

再次刷新页面,没有反应。

接下来,我们发送 POST 请求到 http://localhost:8003/actuator/refresh 这个接口,用 postman 之类的工具即可,此接口就是用来触发加载新配置的,返回内容如下:

在这里插入图片描述

之后,再次访问 RESTful 接口,http://localhost:8003/getAutoInfo

在这里插入图片描述

可以看到这个接口获取的数据已经是最新的了,说明 refresh 机制起作用了。

但是当我们访问http://localhost:8003/getInfo,获取的还是旧数据,这与 @Value 注解的实现有关,所以,我们在项目中就不要使用这种方式加载配置了。

改为自动刷新

github 提供了一种 webhook 的方式,当有代码变更的时候,会调用我们设置的地址,来实现我们想达到的目的。

1、进入 github 仓库配置页面,选择 Webhooks ,并点击 add webhook

在这里插入图片描述

2、之后填上回调的地址,也就是上面提到的 http://localhost:8003/actuator/refresh 这个地址,但是必须保证这个地址是可以被 github 访问到的。如果是内网就没办法了。这也仅仅是个演示,一般公司内的项目都会有自己的代码管理工具,例如自建的 gitlab,gitlab 也有 webhook 的功能,这样就可以调用到内网的地址了。

在这里插入图片描述

四,自动刷新

使用 Spring Cloud Bus 来自动刷新多个端:

Spring Cloud Bus 将分布式系统的节点与轻量级消息代理链接。这可以用于广播状态更改(例如配置更改)或其他管理指令。一个关键的想法是,Bus 就像一个扩展的 Spring Boot 应用程序的分布式执行器,但也可以用作应用程序之间的通信渠道。

—— Spring Cloud Bus 官方解释

这里不做介绍了,可以参考这篇文章来实现:

Spring Cloud教程–使用Spring Cloud Bus自动刷新配置更改

五,写到最后

这里在用客户端拉取配置时遇到一个这样的问题,这里强调一下:

我用spring boot 2.4.1和spring cloud 2020.0.0-RC1版本去获取配置时获取不到。

把版本改为spring boot 2.3.4.RELEASE 和 spring cloud Hoxton.SR8版本获取配置正常

暂时不清楚为什么,可能新的版本有了变化,如果大家知道原因的话可以在评论区留言告知!!!

本文中所用到的例子已上传码云:

点击这里查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃透Java

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值