spring cloud config学习一:快速入门

为什么要统一管理配置?

  • 集中管理配置文件
  • 不同环境不同配置
  • 运行期间动态调整配置
  • 自动刷新

分布式配置中心

spring cloud configspring cloud团队创建的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端和客户端两部分,其中服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息,加密/解密信息等访问接口,而客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。spring cloud config实现了对服务端和客户端中环境变量和属性设置的抽象映射,所以它除了适用于spring构建的应用程序之外,也可以在任何其他语言运行的应用程序中使用。由于spring cloud config实现的配置中心默认采用git来存储配置信息,所以使用spring cloud config构建的配置服务器,天然就支持对微服务应用配置信息的版本管理,并且可以通过git客户端工具来方便地管理和访问配置内容。当然它也提供了对其他存储方式的支持,比如说svn仓库,本地化文件系统。

快速入门

构建一个基于git存储的分布式配置中心,并在客户端中演示如何通过配置指定微服务应用的所属配置中心,并让其能够从配置中心获取配置信息并绑定到代码的整个过程。

构建配置中心

创建一个名为config-server-git的服务

第一步,加入依赖:

<dependencies>
   <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>
</dependencies>

我构建的是父子依赖,关于spring cloud的版本定义可以在父依赖中查看,相关代码可以在博客最下方查看。

第二步,创建springboot程序主类,加上注解@EnableConfigServer,开启spring cloud config的服务端功能。

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

第三步,在application.yml中添加配置服务的基本信息以及git仓库的相关信息

spring:
  application:
    name: config-server-git
  cloud:
    config:
      server:
        git:
          uri: http://git.oschina.net/zhihaomiao/config-repo-demo
          username: zhihao.miao
          password: 13579qwertyu
          search-paths: config-repo
server:
  port: 9090

其中git的配置分别表示如下内容

  • spring.cloud.config.server.git.uri: 配置的git仓库位置
  • spring.cloud.config.server.git.search-paths: 配置仓库路径下的相对搜索位置,可以配置多个
  • spring.cloud.config.server.git.username: 访问git的用户名
  • spring.cloud.config.server.git.password: 访问git仓库的用户密码

配置规则详解

在git配置信息中指定的仓库位置,http://git.oschina.net/zhihaomiao/config-repo-demo/config-repo目录下创建五个不同的配置文件

zhihao.yml
zhihao-dev.yml
zhihao-test.yml
zhihao-pro.yml
application.yml

内容分别是:
zhihao.yml

from: git-default-1.0
spring:
  datasource:
    username: user_default

zhihao-dev.yml

from: git-dev-1.0
spring:
  datasource:
    username: user_dev

zhihao-test.yml

from: git-test-1.0
spring:
  datasource:
    username: user_test

zhihao-pro.yml

from: git-pro-1.0
spring:
  datasource:
    username: user_pro

application.yml

from: git-pro-1.0
spring:
  datasource.
    username:
      zhihao.miao1

为了测试版本控制,在git仓库的master分支中,我们为from属性加入1.0的后缀,同时创建一个config-label-test分支,并将各配置文件中的值用2.0做为后缀.

完成上面的工作我们就可以通过url来访问这些配置内容了。

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

上面的url会映射{application}-{profile}.yml对应的配置文件,其中{label}对应git上不同的分支,默认是master。我们可以尝试构造不同的url来访问不同的配置内容,比如,要访问config-label-test分支,zhihao应用的prod环境,就可以访问这个url:http://localhost:9090/zhihao/pro/config-label-test

{
  name: "zhihao",
  profiles: [
      "pro"
  ],
  label: "config-label-test",
  version: "13c5f9da27b75ea85b1585803a39b00d8a9b75d4",
  state: null,
  propertySources: [
      {
          name: "http://git.oschina.net/zhihaomiao/config-repo-demo/config-repo/zhihao-pro.yml",
          source: {
              from: "git-pro-3.0",
              spring.datasource.username: "user_pro3.0"
          }
      },
      {
          name: "http://git.oschina.net/zhihaomiao/config-repo-demo/config-repo/zhihao.yml",
          source: {
              from: "git-test-2.0",
              spring.datasource.username: "user_default"
          }
      },
      {
          name: "http://git.oschina.net/zhihaomiao/config-repo-demo/config-repo/application.yml",
          source: {
              from: "git-pro-2.0",
              spring.datasource.username: "zhihao.miao2"
          }
      }
  ]
}

我们看到json中返回了应用名是zhihao,环境是prod,分支名是config-label-test,以及default环境和prod环境的配置内容,还包括applocation.yml的内容。另外之前提到的version,也可以观察到,对应于最后提交的git的commit_id

也可以输入http://localhost:9090/abc/pro/config-label-test,此时没有abc.yml文件,就会去application.yml文件中查找,所以application.yml可以匹配任何{application}

{
    name: "abc",
    profiles: [
        "pro"
    ],
    label: "config-label-test",
    version: "13c5f9da27b75ea85b1585803a39b00d8a9b75d4",
    state: null,
    propertySources: [
        {
            name: "http://git.oschina.net/zhihaomiao/config-repo-demo/config-repo/application.yml",
            source: {
                from: "git-pro-2.0",
                spring.datasource.username: "zhihao.miao2"
            }
        }
    ]
}

同时,我们可以看到config-server-git的控制台中还输出了下面的内容,配置服务器在从git中获取了配置信息后,会存储一份在config-server-git的文件系统中,实质上config-server-git是通过git clone命令将配置内容复制了一份在本地存储,然后读取这些内容并返回给微服务应用进行加载。

2017-08-15 22:10:07.568  INFO 28701 --- [io-9090-exec-10] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5ac2c286: startup date [Tue Aug 15 22:10:07 CST 2017]; root of context hierarchy
2017-08-15 22:10:07.579  INFO 28701 --- [io-9090-exec-10] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/p0/kw_s_8xj2gqc929nys7cj2yh0000gn/T/config-repo-2847833657021753497/config-repo/application-pro.yml
2017-08-15 22:10:07.579  INFO 28701 --- [io-9090-exec-10] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/p0/kw_s_8xj2gqc929nys7cj2yh0000gn/T/config-repo-2847833657021753497/config-repo/application.yml
2017-08-15 22:10:07.579  INFO 28701 --- [io-9090-exec-10] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5ac2c286: startup date [Tue Aug 15 22:10:07 CST 2017]; root of context hierarchy

config-server-git通过从git在本地的仓库暂存,可以有效的防止当git仓库出现故障而引起无法加载配置信息的情况。我们可以通过断开网络(断开wifi),再次发起从http://localhost:9090/zhihaomiao/pro/config-label-test请求,在控制台中可以输出如下内容,这些内容源于之前访问时存在于config-server-git服务本地文件系统中的配置信息。

2017-08-15 22:23:15.002  WARN 28701 --- [nio-9090-exec-5] .c.s.e.MultipleJGitEnvironmentRepository : Could not fetch remote for config-label-test remote: http://git.oschina.net/zhihaomiao/config-repo-demo
2017-08-15 22:23:15.074  INFO 28701 --- [nio-9090-exec-5] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7060493e: startup date [Tue Aug 15 22:23:15 CST 2017]; root of context hierarchy
2017-08-15 22:23:15.088  INFO 28701 --- [nio-9090-exec-5] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/p0/kw_s_8xj2gqc929nys7cj2yh0000gn/T/config-repo-2847833657021753497/config-repo/application-pro.yml
2017-08-15 22:23:15.089  INFO 28701 --- [nio-9090-exec-5] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/var/folders/p0/kw_s_8xj2gqc929nys7cj2yh0000gn/T/config-repo-2847833657021753497/config-repo/application.yml
2017-08-15 22:23:15.089  INFO 28701 --- [nio-9090-exec-5] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7060493e: startup date [Tue Aug 15 22:23:15 CST 2017]; root of context hierarchy

通过http访问git server资源的格式:

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

比如

http://localhost:9090/config-label-test/abc-pro.yml

等等。

客户端配置映射

如何在微服务应用中获取上面的配置信息?

  • 创建一个应用config-client,并在pom文件中引入依赖:
    <dependencies>
        <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.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
  • 创建springboot的应用主类:
@SpringBootApplication
public class ConfigClientApplication {

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


}
  • 创建bootstrap.yml配置,来获取配置文件的config-server-git位置,如下:
spring:
  application:
    name: zhihaomiao
  cloud:
    config:
      uri: http://localhost:9090/
      profile: pro
      label: config-label-test
server:
  port: 8080

上述配置参数与git中存储的配置文件中各个部分的对应关系如下:

  • spring.application.name: 对应配置文件规则中的{application}部分
  • spring.cloud.config.profile:对应配置文件规则中{profile}部分
  • spring.cloud.config.label:对应配置文件规则中的{label}部分
  • spring.cloud.config.uri:配置中心config-server的地址。

这里需要格外注意,上面的属性必须配置在bootstrap.yml中,这样config-server中的配置信息才能被正确加载。springboot对配置文件的加载顺序,对于本应用jar包之外的配置文件加载会优于应用jar包内的配置内容,而通过bootstrap.ymlconfig-server-git的配置,使得该应用会从config-server-git中获取一些外部配置信息,这些信息的优先级比本地的内容要高,从而实现了外部化配置。

springboot应用配置文件加载的顺序是bootstrap.yml-> config server中的配置 -> application.yml中的配置,这样的顺序进行加载。

如果在application.yml中配置和远程配置相同的配置
application.yml

from: git-pro-1.0
spring:
  datasource:
    username: user_pro

那么application.yml中不会覆盖当前在config server中的配置,并且读取的还是远程仓库的配置,那么如何进行属性覆盖呢,可以看下面的博客。

@RestController
public class ConfigClientController {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${from}")
    private String from;

    @GetMapping("/index")
    public String index(){
        log.info("username="+username+",form=="+from);
        return "username="+username+",form=="+from;
    }
}

访问

http://localhost:8080/index

页面显示:

username=user_pro,form==git-pro-2.0

服务端详解

基本结构
  • 远程git仓库:用来存储配置文件的地方,快速入门中应用名为zhihao的多环境配置文件:zhihao-{profile}.properties.
  • config server:这是我们快速入门中构建的分布式配置中心,config-server-git项目,在该工程中指定了所要连接的git仓库位置以及账户,密码等连接信息。
  • 本地git仓库:在config server的文件系统中,每次客户端请求获取配置信息时,Config Server从git仓库中获取最新的配置到本地,然后在本地git仓库中读取并返回。当远程仓库无法获取时,直接将本地的内容返回。
  • Service A,Service B:具体的微服务应用,他们指定了config Server地址,从而实现从外部化获取应用自己要用的配置信息。这些应用在启动的时候,会向config server请求获取配置信息来进行加载。

客户端应用从配置管理中获取配置信息遵从下面的执行流程:

  1. 应用启动时,根据bootstrap.yml中配置的应用名{application},环境名{profile},分支名{label},向config server请求获取配置信息
  2. config server根据自己维护的git仓库信息和客户端传递过来的配置信息去查找配置信息。
  3. 根据git clone命令将找到的配置信息下载到Config Server的文件系统中
  4. Config Server创建Spring的ApplictionContext实例,并从git本地仓库中加载配置文件,最后将这些配置内容读取出来返回给客户端应用。
  5. 客户端应用在获取外部配置文件后加载到客户端的ApplicationContext实例,该配置内容的优先级高于客户端jar包内部的配置内容,所以在jar包中重复的内容不再被加载

Config Server巧妙的通过git clone将配置信息存于本地,起到了缓存的作用,即使当git服务端无法访问的时候,依然可以取Config Server中缓存内容进行试验。

参考文档
官网The Bootstrap Application Context
官网Quick Start
官网Client Side Usage

本博客代码
代码地址
配置仓库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容