Spring Cloud 学习——7. Spring Cloud Config

1. 前言

  本文介绍一个 通过 Spring Cloud Config + git 实现 Spring Cloud 项目的配置中心化的简单实践。

  在一个分布式系统中,存在着各种微服务,而每一种服务可能都有几十甚至几百个实例在运行。虽然这些实例被分别部署在不同的机器上(或者网络节点中),但是他们需要一致对外提供服务,所以他们必须对所有的配置项都具有相同的配置值。而如果将这些配置项都保存在各个实例的本地上,那么一份配置就会存在几十上百个副本,这种情况下,一旦需要修改某一个配置值,这种运维上的难度可想而知。所以,在一个分布式系统中,单独建立一个配置中心是很有必要的。Spring Cloud 当然也考虑到了这一点,Spring Cloud Config提供了 解决方案。

  Spring Cloud Config 分为 config server 和 config client,config server 即是配置中心,它负责管理所有的配置;其它需要使用配置的服务模块就是 config client。所有的 config client 都从 config server 拉去配置,这样就保证了同一种微服务的所有实例都具有相同的配置值,并且只需要维护一份配置值。

  Spring Cloud Config 支持将配置保存在本地或者 vcs服务器上(如:git、svn)。一般实际项目中都建议将配置存放到 git 上,好处有:

    1.1. git 本身就是一个版本控制工具,用它来管理配置,对于项目的迭代升级以及运营的支持都非常方便。升级出了问题也方便回退,还可以查看历史版本;

    1.2. git 本身支持多分支,而实际项目可能也存在多个分支,不同分支的配置提供给对应分支的项目,不用为同一个项目的多个分支分别维护配置仓库;

    1.3. git 的云厂商非常成熟,如:github、gitee 等,而且免费;

  所以本文也是以将配置保存在 git 上为例。

2. 搭建 config server

  2.1. 新建一个 spring boot 模块

  2.2. 添加依赖,版本自选

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

  2.3. 启用 config server 服务器

    启动类添加注解  @EnableConfigServer

  2.4. 新建git仓库,放入配置文件,示例:

      

    在本例中:我的配置文件仓库名为 onezai-cloud-config ;使用 master 分支;我将所有配置文件放到 config 目录下(避免与  .idea 和 readme 这些文件混合在一起);我的配置文件名为 sys-dev.properties;我的配置文件中有两个配置项 username 和 nickname。

  2.5. 指定存放配置文件的 git 仓库信息,在 application 文件中添加配置

spring.cloud.config.server.git.uri=https://gitee.com/xxx/xxx
spring.cloud.config.server.git.search-paths=config
spring.cloud.config.server.git.username=xxx
spring.cloud.config.server.git.password=xxx

  其中:

    2.5.1. git.uri 指定仓库地址目录,一般由 git 服务商域名+个人空间地址+仓库名组成;

    2.5.2. search-paths 指定查找目录,它是相对于仓库根目录的。即只在指定仓库的这个目录下查找配置文件;

    2.5.3. git.username 和 git.password 分别指定访问仓库的用户名和密码,一般配置文件都是比较机密的,所以建议放在私有仓库通过账号密码去访问;

  2.6. 启动 config server模块,验证是否能从 git 上拉取配置文件

    在浏览器访问 http://localhost:7300/master/sys-dev.properties

      

    其中:

      7300 是 config server 模块的服务地址;

      master 是仓库分支名(因为 master 是默认分支,可以省略,所以也可以这样访问:http://localhost:7300/sys-dev.properties);

      虽然两个配置项的顺序跟仓库源文件不一致,虽然

  2.7. 从日志看工作过程

    这是上述访问过程中 config server 的日志:

      

    所以,在访问配置的时候,config server 会将访问的配置文件拉取到本地的临时目录存放。既然在本地放了副本,那我猜想在访问配置的时候,如果此时 config server 访问不到 git 仓库,也能返回结果,接下来我们验证一下:将仓库中 username 的值从 coding_one_v1 改为 coding_one_v2,然后把本机网络断了,再访问一下上述地址

      

      

      结果:

      

    说明我们的猜测是正确的。这样在本地放一个副本的策略,在一定程度上提高了可用性,毕竟配置这种东西不是经常改动的,而网路故障时有可能发生的,但是刚好在系统修改了配置需要更新的时候同时又发生了网络故障这种概率就非常小了。

  到这里,我们还只是完成了 config server 的搭建和验证,接下来我们搭建 config server。

3. 搭建 config server

  3.1. 新建一个 springboot 模块,该模块通常是业务服务模块。

    在本例中,我沿用了该系列前面文章的 demo 代码,所以无需新建模块,直接使用已经存在的 sys 模块。前面文章的链接在文章结尾统一目录。

  3.2. 添加依赖,版本自选

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>

  3.3. 添加配置,指定 config server 信息

spring.cloud.config.uri=http://localhost:7300/
spring.cloud.config.profile=@[email protected]
spring.cloud.config.label=master

    其中:

      3.3.1. config.uri 指定 config server 的服务地址。这种是直接配置的方式,还有方法是将 config server 也注册到 eureka server ,然后通过服务发现去找到 config server(这里不做示例);

      3.3.2. config.profile 指定需要获取哪种环境的配置文件,一般有 dev/test/pro等,@[email protected] 是取当前实例运行的环境,环境的配置可以通过 maven 的 <profiles> 节点去完成,然后在打包时指定或者运行 java -jar 命令时使用 --spring.profiles.active=xxx 参数指定;

      3.3.3. config.label 指定需要从 git 仓库的哪个分支获取配置;

      3.3.4. 一个 git 仓库中可能会存放很多 config client 的配置文件,而 config server 会根据 config client 的服务名( spring.application.name )去区分配置文件。config 支持的配置文件名和请求参数对应规则有:       

        • / { 应用名 } / { 环境名 } [ / { 分支名 } ]
        • / { 应用名 } - { 环境名 }.yml
        • / { 应用名 } - { 环境名 }.properties
        • / { 分支名 } / { 应用名 } - { 环境名 }.yml
        • / { 分支名 } / { 应用名 } - { 环境名 }.properties

         不指定分支名的情况下会查找仓库的默认分支。

    另外,在我的例子中,上述配置需要在 bootstrap 和 application 文件中都写上,暂时还不明白为什么,可能跟 spring boot 的加载顺序有关系,后面再去解决吧!

  3.4. 新建配置类

@Component
@RefreshScope
public class CommonConfig {
    @Value("${username}")
    private String username;

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
}

    其中, @Component  注解将配置类实例化,这样就可以在项目中使用  @Autowired 注入到其它类对象中直接使用了;通过在配置类属性添加  @Value  注解来将指定的配置项值注入到对应属性中; @RefreshScope  注解则是动态刷新配置需要用到的,动态刷新配置后面会讲。

  3.5. 使用配置  

@RestController
@RequestMapping("/")
public class HomeController {
    @Autowired
    EurekaClient eurekaClient;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    UserClient userClient;
    @Autowired
    CommonConfig commonConfig;

    @GetMapping("/getUser/{id}")
    public User getUser(@PathVariable("id")String id){
        User user = userClient.getUserById(id);
        System.out.println("user:\n" + JSONObject.fromObject(user).toString());
        System.out.println("从 config server 获取的配置项:username=" + commonConfig.getUsername());
        return user;
    }

    访问 /getUser/{id}服务,打印结果如下:

      

    获取配置成功。

  

4. 至此,通过 Spring Cloud Config + git 实现分布式系统的配置中心化已经实现了。

  本例只是一个最简单实践,在实际项目中,还要考虑 config server 的高可用性。

  后面文章会介绍怎么实现 spring cloud config 配置的动态刷新。

原文地址:https://www.cnblogs.com/coding-one/p/12310306.html

时间: 2024-11-05 21:37:53

Spring Cloud 学习——7. Spring Cloud Config的相关文章

Spring Cloud学习--配置中心(Config)

Spring Cloud学习--配置中心(Config) 一 Spring Cloud Config简介 二 编写 Config Server 三 编写Config Client 四 使用refresh端点手动刷新配置 五 Spring Config Server与Eurelka配合使用 六 Config Server的高可用 一. Spring Cloud Config简介 微服务要实现集中管理微服务配置.不同环境不同配置.运行期间也可动态调整.配置修改后可以自动更新的需求,Spring Cl

Spring框架学习02——Spring IOC 详解

1.Spring IOC的基本概念 IOC(Inverse of Control)反转控制的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理.当某个Java对象(调用者)需要调用另一个Java对象(被调用者)时,在传统编程模式下,调用者通常会采用“new 被调用者”的代码方式来创建对象.这种方式会增加调用者与被调用者之间的耦合性,不利于后期代码的升级与维护.当Spring框架出现后,对象的实例不再由调用者来创建,而是由Spring容器来创建.Spring容器会负责控制程序之

Spring Cloud 学习 (六) Spring Cloud Config

在实际开发过程中,每个服务都有大量的配置文件,例如数据库的配置.日志输出级别的配置等,而往往这些配置在不同的环境中也是不一样的.随着服务数量的增加,配置文件的管理也是一件非常复杂的事 在微服务架构中,需要有统一管理配置文件的组件,例如 Spring Cloud 的 Spring Cloud Config.阿里的 Diamond.百度的 Disconf.携程的 Apollo 等 新建 spring-cloud-config-server 从本地读取配置 pom <parent> <arti

Spring Cloud 学习 (八) Spring Boot Admin

Spring Boot Admin 用于管理和监控一个或者多个 Spring Boot 程序 新建 spring-boot-admin-server pom <parent> <artifactId>spring-cloud-parent</artifactId> <groupId>com.karonda</groupId> <version>1.0.0</version> </parent> <mode

Spring的学习____X. spring 和mybatis的整合

(本案例是idea下的maven工程) 案例一:mybatis的回顾: 整体流程的回顾: mybatis: 1.实体类(User)---->属性名和数据库中字段名相对应 2.接口(UserMapper----->对数据库的增删改查的业务操作的定义 3.接口的配置文件(UserMapper.xml)----> mappers的namespace属性要写对应的接口: 再写UserMapper接口中增删改查的SQL语句 4.mybatis 的核心配置文件(mybatis-config.xml)

Spring+Maven学习实验- Spring AOP面向切面编程(二)

在 Spring AOP 中,有 3 个常用的概念,Advices . Pointcut . Advisor ,解释如下: Advices :表示一个 method 执行前或执行后的动作. Pointcut :表示根据 method 的名字或者正则表达式去拦截一个 method . Advisor : Advice 和 Pointcut 组成的独立的单元,并且能够传给 proxy factory 对象. 我们可以用名字匹配法和正则表达式匹配法去匹配要拦截的 method . 1 Pointcut

Spring MVC 学习笔记 spring mvc Schema-based configuration

Spring mvc 目前支持5个tag,分别是 mvc:annotation-driven,mvc:interceptors,mvc:view-controller, mvc:resources和mvc:default-servlet-handlermvc:annotation-driven   注册 DefaultAnnotationHandlerMapping 和AnnotationMethodHandlerAdapter两个bean,及一系列缺省的messageconverter(需要c

Spring Boot学习笔记——Spring Boot与Redis的集成

一.添加Redis缓存 1.添加Redis起步依赖 在pom.xml中添加Spring Boot支持Redis的依赖配置,具体如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </

Spring boot 学习六 spring 继承 mybatis (基于注解)

MyBatis提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,这些都是建立动态语言和让MyBatis执行这些语言使用基于注解的mybatis的方法,还是比较好用的. 一 首先是定义mapper, @ SelectProvider去声明类(CitySqlProvide)和方法名(findByState), public interface CityMapper { @SelectProvider(ty