每次有人提到极简这个词,都会说极简不是偷懒,是一种 balabala ……

我想说: 我,就是要偷懒!

下面介绍可能是最简单的 spring 的配置中心(也许用某个框架的配置中心这种词不太对,先就这样吧)。

这个配置中心依赖两个 spring 的组件: spring-cloud-configspring-cloud-actuator

spring-cloud-config

只需两分钟即可搭建一个 spring-cloud-config 的配置中心:

引入 maven 依赖

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

通过配置中心自身的配置文件指定一个配置文件(其他服务的配置)存在的路径,以及访问的一些设置,例如

spring:
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/configurations
  profiles:
    active: native
  security:
    user:
      password: dev

server:
  port: 8888

其中 native.search-locations: classpath:/path 这种方法能用,但是还不够好,可以使用这样的配置:

spring:
  application:
    name: configuration-center-name
  cloud:
     config:
        server:
          git:
            uri: https://github.com/Kicey/config-repo
            username: Kicey
            password: duang
            default-label: master # 配置文件分支
            search-paths: config  # 配置文件所在根目录

没错,可以使用 git 仓库,只需要在配置文件写上相应的配置,其余将自动完场,那么就能利用 git 的版本控制等一系列功能!突出一个懒字。

(注意:请按照 spring-cloud-config 的规范命名配置文件,懒得写了, baidu/google 一下)

添加注解

@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }
}

这是一个普通的 spring 应用的入口,只是多了一个 @EnableConfigServer 的注解。

好了,完成!

好吧,还没有,现在的配置中心能正常提供配置(直接可通过 http 请拿到数据),但是还缺点什么。

还缺配置的更新和使用配置的服务。

服务读取配置

在依赖这个配置中心的应用中

加入依赖

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

bootstrap.yml 中加入配置

(关于 bootstrap.yml 和 application.yml 请看这篇文章 application.yml与bootstrap.yml的区别 - 简书 (jianshu.com),放心,同样简单)

spring:
  application:
    name: gateway
  cloud:
    config:
      uri: http://${CONFIG_HOST:localhost}:${CONFIG_PORT:8888}
      fail-fast: true
      password: ${CONFIG_PASS:dev}
      username: user

结束,到此位置配置中心上的配置就能使用了,但是还存在一个问题——配置更新。

在使用 spring-cloud-config 的情况下,从配置中心的读取的配置被当作从本地的 application.yaml 中的配置(这么说有点不妥,但是理解很快,真要说是 spring 对环境变量作了抽象,这两种配置方式在抽象上是等价的)。也就是说,spring 只在启动应用时加载一次配置,之后即使 git 仓库中的配置更新了,它也不会去拉取配置。

spring actuator

spring-cloud-config-server 和读取其配置的服务都没有自动热更新,就是说它们在默认的情况下只在程序启动之后去读一次配置,之后你再改是无效的。

注意:下面的更改均在读取配置的服务中,而不是配置中心!

为了实现配置的热更新,我们需要 actuator。同样简单

首先,加依赖

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

再加配置文件内容

management:
  endpoints:
    web:
      exposure:
        include: "*"
server:
  port: ${PORT:8888}

好了,完成了。

之后 post 服务(非配置中心)的 /actuator/refresh 就会刷新配置。你可能会问,客户端刷新配置能懂,毕竟加入了新的依赖,你服务端咋也刷了?那么,你猜 spring 在设计的时候服务请求刷新配置,然后配置是通过 spring-cloud-config 获取的,那么配置中心得到刷新调用后会不会更新自己的数据?

(也可以在配置中心上使用 actuator 在没有一个服务的配置刷新请求时,也能完成配置中心自己的更新)。

完。

等等,还需要提醒的是注意 @Value 类似的读取配置的注解,只在启动时读取一次,即使之后本地应用中的配置都更新了,要动态的配置请使用其他的方式吧。