美文网首页spring cloudspringcloud学习
spring cloud config学习一:快速入门

spring cloud config学习一:快速入门

作者: 二月_春风 | 来源:发表于2017-08-19 17:03 被阅读214次

    为什么要统一管理配置?

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

    分布式配置中心

    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

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

    相关文章

      网友评论

        本文标题:spring cloud config学习一:快速入门

        本文链接:https://www.haomeiwen.com/subject/qegprxtx.html