暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring Cloud Config开发教程

data之道 2018-03-19
374

综述

    一般项目的配置文件都散落在各自应用里,如果改为Spring Cloud Config的方式,就能统一管理资源文件而且也能对属性进行实时刷新。Client端获取远程资源时,直接映射到Spring Environment和PropertySource对象,可无缝集成到Spring项目,也支持在非Spring应用程序使用。

WHY


    我们项目的配置文件都外部化在本地文件系统,对于分布式部署的应用,同样也会在每台服务上存一份,基于这个前提,主要槽点

    1、随着线上应用越来越多,配置文件也同步增加,对配置文件的管理就变得越来越棘手.

    2、若更新项目里的一个配置项,就要重启应用,这个代价也还是蛮大的.

    Spring Cloud Config的分布式统一管理、动态刷新等特性,能完美解决我们的痛点。我们项目大部分后端项目都用Spring Boot开发,Cloud Config天生就支持Spring框架,对client端几乎是无侵入,没有重新学习成本,这就使得升级使用Cloud Config变得水道渠成。

WHAT


    Spring Cloud是在Spring Boot之上构建的,而Spring Cloud Config是Spring Cloud的一个子项目,不依赖于其他Spring Cloud项目就能独立使用。Spring Cloud Config分为Server和Client,Server默认使用git作为后端存储,也支持SVN和本地两种方式。git支持分支和标签版本,随着应用在dev、test、prod环境中部署,git很容易在不同环境之间进行配置切换。

    Config Server:

  • RESTful API管理外部配置

  • 对属性值进行加解密,提高安全性

  • 嵌入到Spring Boot应用非常轻松,只需增加@EnableConfigServer注解

    Config Client:

  • 绑定到配置服务器、启动时调用服务端接口并使用远程属性来初始化Spring环境

  • 对属性值进行加解密

架构图:

Server开发


    Config Server是一个独立的应用,统一管理外部化资源文件,将配置文件发布成RESTful接口,供Client端调用。pom文件增加spring-cloud-config-server依赖:   

<dependency>
   <groupId>
org.springframework.cloud</groupId>
   <artifactId>
spring-cloud-config-server</artifactId>
   <version>
${spring.cloud.config.version}</version>
</dependency>

    spring-cloud-config-server内部依赖了spring-cloud-config-client和spring-boot-starter-web,这就可以直接开发一个Spring Boot应用程序,在启动类上加@EnableConfigServer注解,声明这是一个Config Server:

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

    application.yml配置文件:

management.security.enabled=false,禁用Spring Boot监控模块(Actuator)的安全认证,否则需要权限才能访问/refresh、/env、/metrics、/trace、/health等Endpoints,在生产环境强烈建议开启。

spring.cloud.config.server.git.uri:配置文件所在的git地址,如果是http打头,uri要以.git结尾

spring.cloud.config.server.git.username/password:访问git的用户

spring.cloud.config.server.git.searchPaths:配置文件搜索路径,搜索目录支持 {application}、{profile}、{label}占位符。application:对应client配置的spring.cloud.config.name或spring.application.name;profile:对应client spring.cloud.config.profile或spring.profiles.active配置项;label:表示git上的分支,对应client spring.cloud.config.label配置项,默认master。

spring.cloud.config.server.git.clone-on-start:Config Server启动时是否clone git仓库到本地,建议设为true,否则需要client首次请求时才clone仓库,会影响client首次的请求效率

spring.cloud.config.server.git.basedir:配置文件本地存储的目录

    根据上面配置的searchPaths,新建配置文件,并提交到git上。需注意的是:git仓库只支持yml、properties文件格式,而且文件名是{application}-{profile}或{application}。

    远程请求API:http://{Config Server}:{port}/{application}/{profile}/[label],lable默认是master

Client开发


   spring-cloud-starter-config可以便捷的进行Client端应用开发,starter-config依赖了config-server、config-client,这样也不用手动导入spring boot,如果只依赖了spring-cloud-starter-client,还需要依赖spring-boot相关jar。后续过程和开发一般spring boot一样,获取属性值的方式也没任何差异。bootstrap.properties相比一般Spring Boot应用多了Cloud Config特有配置项:

spring.cloud.config.failFast=true
spring.cloud.config.uri= http://localhost:5556
spring.cloud.config.name=test
spring.cloud.config.profile=prod
spring.cloud.config.label=master

x.x.x.uri:Config Server地址

x.x.x.name:Server接收到的application,如果没配会取spring.application.name的值

x.x.x.profile:Server接收到的profile,如果没配会取spring.profiles.active的值

x.x.x.lable:Server接收到的lable,默认master

     @Value方式获取属性:

@Value("${hbase.zk.quorum}")
private String zkHost;

    Environment对象获取属性:

@Autowired
private Environment env;
env.getProperty("hbase.zk.quorum")

    根据属性名前缀封装成对象:

    其它配置项:    

    spring.cloud.config.enabled=false,会禁用从Spring Cloud Config Server加载配置项

Client配置文件加载


      为什么build client端时Spring Cloud Config相关配置项一定要在bootstrap.yml/properties文件里呢?

    Spring Boot会在启动之前,遍历各个jar包META-INF目录下的spring.factories文件,spring-cloud-config-client jar包里的spring.factories:

    Spring Cloud会创建bootstrap上下文,bootstrap上下文,是主应用程序的父上下文,对应的默认配置文件bootstrap.yml或bootstrap.properties。在准备bootstrap上下文阶段将BootstrapConfiguration对应的配置项实例化并将其加入到IOC容器中,BootstrapConfiguration定义了Bootstrap启动的组件。在实例化ConfigServiceBootstrapConfiguration Bean时,也会实例化Client配置属性Bean:

    spring.cloud.config开头的配置项注入到Bean:

    由上可知bootstrap处在加载链的最前端,而ConfigClientPropertiesde是在创建bootstrap上下文时实例化的,也就是在应用程序初始化之前就完成了Spring Cloud Config配置属性的加载。如果bottstrap上下文配置文件没有配置spring.cloud.config相关的属性,那只会实例化属性默认的ConfigClientProperties Bean对象

Server配置文件加载


    创建server端时,为什么Spring Cloud Config相关属性可以在bootstrap.yml/properties或application.yml/properties内配置?

     在Server端的spring.factories的配置项:

    初始化bootstrap上下文时会实例化ConfigServerBootstrapConfiguration Bean,但只有在spring.cloud.config.server.bootstrap=true时才实例化,而默认是false。

    spring.cloud.config.server打头的配置项注入到ConfigServerProperties Bean:

    在spring.cloud.config.server.bootstrap=false的情况下,bootstrap初始化上下文时不会实例化ConfigServerProperties Bean,那又是在什么时候实例化呢?

    初始化application上下文时会将EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,并加载到IoC容器,application上下文的默认配置文件application.yml/properties。    

    也就是说,如果在初始化bootstrap上下文时没实例化ConfigServerProperties Bean,那就会在初始application上下文时实例化。

通过参数指定加载的配置文件

    --spring.cloud.bootstrap.location:指定bootstrap上下文加载的配置文件

    --spring.config.location:指定application上下文加载的配置文件

RefreshScope


    Config支持Client端不重启动态刷新,可以解决只能获得初始配置的问题,但Client不能主动感知配置的变化,Spring提供了两中不同方案,一种是对Client进行post /refresh请求,添加@RefreshScope注解的Bean会进行动态刷新;另一种是使用Spring Cloud Bus

    假设如下场景,在使用DataSource获得一个数据库连接的是时候,当修改了远程配置中心的数据库连接字符串,我们可以请求client /refresh接口,根据修改后的配置项重新获取一个新的数据库连接,但是如果所有微服务节点的配置都需要手动去刷新的话,那必然是一个繁琐的工作,而且随着系统的不断扩张,会变得越来越难以维护。Spring Cloud Bus将分布式的节点用轻量的消息代理连接起来,可以用于广播配置文件的更改或者服务之间的通讯,后续有时间再聊集成消息总线。

本文为原创,欢迎分享到朋友圈。

文章转载自data之道,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论