天天看点

Spring Cloud之(二十)SpringCloud Config

二十、SpringCloud Config

20.1 什么是配置中心?

  • 配置中心概述

    对于传统的单体应用而言,常使用配置文件来管理所有配置,比如SpringBoot的application.yml文件,但是在微服务架构中全部手动修改的话很麻烦而且不易维护。

    微服务的配置管理一般有以下需求:

    1. 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的。
    2. 不同环境不同配置,比如数据源配置在不同环境(开发,生产,测试)中是不同的。
    3. 运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池大小等
    4. 配置修改后可自动更新。如配置内容发生变化,微服务可以自动更新配置
    综上所述对于微服务架构而言,一套统一的,通用的管理配置机制是不可缺少的总要组成部分。常见的做法就是通过配置服务器进行管理。
  • 常见配置中心

    Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。

    Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

    Disconf 专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」包括百度、滴滴出行、银联、网易、拉勾网、苏宁易购、顺丰科技等知名互联网公司正在使用!「disconf」在「2015 年度新增开源软件排名 TOP 100(OSC开源中国提供)」中排名第16强。

20.2 Spring Cloud Config简介

Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。

Spring Cloud之(二十)SpringCloud Config

Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以为所有环境中的应用程序管理其外部属性。它非常适合spring应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。

Spring Cloud Config服务端特性:

  1. HTTP,为外部配置提供基于资源的API(键值对,或者等价的YAML内容)
  2. 属性值的加密和解密(对称加密和非对称加密)
  3. 通过使用@EnableConfigServer在Spring boot应用中非常简单的嵌入。

Spring Cloud Config客户端的特性(特指Spring应用)

  1. 绑定Config服务端,并使用远程的属性源初始化Spring环境。
  2. 属性值的加密和解密(对称加密和非对称加密)

20.3 Spring Cloud Config入门

  • 创建仓库

    Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置文件内容,也可以使用SVN存储,或者是本地文件存储。

    这里我们使用git作为学习的环境使用GitHub时,国内的用户经常遇到的问题是访问速度太慢,有时候还会出现无法连接的情况。如果我们希望体验Git飞一般的速度,可以使用国内的Git托管服务——码云(gitee.com)。和GitHub相比,码云也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示等功能。对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务。

    Spring Cloud之(二十)SpringCloud Config
    文件命名规则:
    1. {application}-{profile}.yml
    2. {application}-{profile}.properties
    3. application为应用名称 profile指的开发环境(用于区分开发环境,测试环境、生产环境等)
  • 搭建服务端程序(configServer)

    为了方便我们调用服务,我们一般新创建一个项目:ebuy-configServer。

  1. 引入依赖
    <!-- 配置中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
               
  2. 配置启动类

    @EnableConfigServer : 通过此注解开启配置中心服务端功能

    package cn.ebuy.configServer;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer  //通过此注解开启配置中心服务端功能
    public class ConfigApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConfigApplication.class,args);
        }
    }
               
  3. 配置application.yml

    通过

    spring.cloud.config.server.git.uri

    : 配置git服务地址;

    通过

    spring.cloud.config.server.git.username

    : 配置git用户名;

    通过

    spring.cloud.config.server.git.password

    : 配置git密码。
    server:
      port: 10005
    spring:
      application:
        name: ebuy-configServer
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/silent-sparrow/ebuy-config-server.git
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               

    注:

    因为我创建的git仓库是公开的,所以不用设置用户名和密码就可以。

  4. 测试

    启动此微服务,可以在浏览器上通过server端访问到git服务器上的文件:

    Spring Cloud之(二十)SpringCloud Config
  • 修改客户端程序(product)
  1. 引入依赖
    <!-- 配置中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
               
  2. 删除application.yml文件,添加bootstrap.yml文件

    springboot的应用配置文件,需要通过configServer获取,这里就不在需要了。

    而是使用加载级别更高的bootstrap.yml文件进行配置。启动应用时会检查此配置文件,在此文件中指定配置中心的服务地址。会自动的拉取所有应用配置并启用。

    bootstrap.yml:

    spring:
      cloud:
        config:
          name: product #远程git中以product开头的配置文件
          uri: http://localhost:10005 #configServer配置中心远程git地址
          profile: dev
          label: master
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               
    在controller上编写一个方法用于测试(可以获取配置文件中的信息):
    /**
     * 从git中获取配置文件中的信息
     */
    @Value("${productvalue}")
    String productvalue;
    
    @GetMapping("/getProductValue")
    public String getProductvalue()
    {
    	return productvalue;
    }
               
  • 手动刷新

    上面我们已经在客户端取到了配置中心的值,但是当我们修改GitHub上面的值时,服务端能试试获取最新的值,但是客户端读的还是缓存中的值而无法实时获取最新值。

    Spring Cloud之(二十)SpringCloud Config
    这个时候,伙子们不要怕,因为Spring Cloud已经为我们解决了这个问题,那就是客户端使用post去触发refresh获取最新数据,需要依赖

    spring-boot-starter-actuator

    <!--actuator用于心跳检查-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
               
    对应的controller类上加上@RefreshScope注解:
    package cn.ebuy.product.controller;
    
    import cn.ebuy.product.pojo.EasybuyProduct;
    import cn.ebuy.product.service.EasybuyProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("/product")
    @SuppressWarnings("all")
    @RefreshScope
    public class ProductController {
    	/**
    	 * 从git中获取配置文件中的信息
    	 */
    	@Value("${productvalue}")
    	String productvalue;
    
    	@GetMapping("/getProductValue")
    	public String getProductvalue()
    	{
    		return productvalue;
    	}
    }
               
    配置文件中开发端点:
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               
    在postman中访问:localhost:9011/actuator后提交,并再次访问客户端查看结果:
    Spring Cloud之(二十)SpringCloud Config

20.4 配置中心的高可用

在之前的代码中,客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。

  • 服务端改造
  1. 引入依赖
    <!-- 配置中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <!-- eureka注册中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
               
  2. 修改配置文件
    #配置集群(Eureka Client)
    eureka:
      client:
        healthcheck: true #开启健康检查(依赖spring-boot-actuator)
        service-url:
          defaultZone: http://127.0.0.1:9000/eureka/,http://127.0.0.1:8000/eureka/ #配置集群
      instance:
        prefer-ip-address: true #使用ip地址注册
        lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认是90秒)
        lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔
               
    这样server端的改造就完成了。跟之前的套路一样,先启动eureka注册中心,再启动server端,在浏览器中访问localhost:8000/就可以看到此服务已经注册到注册中心了。
    Spring Cloud之(二十)SpringCloud Config
  • 客户端改造
  1. 引入依赖
    <!-- 配置中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <!-- eureka注册中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
               
  2. 修改配置文件
    #配置集群(Eureka Client)
    eureka:
      client:
        healthcheck: true #开启健康检查(依赖spring-boot-actuator)
        service-url:
          defaultZone: http://127.0.0.1:9000/eureka/,http://127.0.0.1:8000/eureka/ #配置集群
      instance:
        prefer-ip-address: true #使用ip地址注册
        lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认是90秒)
        lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔
    spring:
      cloud:
        config:
          name: product #远程git中以product开头的配置文件
          profile: dev
          label: master
          discovery:
            enabled: true
            service-id: ebuy-configServer #远程git地址中的仓库名(配置中心)
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               
  • 高可用

    高可用,毋庸置疑,就是防止某一台服务器down掉之后影响整个系统的使用。一般启动多个configServer服务来避免这个问题。

    跟以前套路一样,我们起两个configServer服务:10005和10006,分别注册到注册中心:

    Spring Cloud之(二十)SpringCloud Config
    分别访问两个服务器和客户端,说明都正常读到了配置信息:
    Spring Cloud之(二十)SpringCloud Config

20.5 消息总线bus

  • 消息总线概述

    在微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线。

    SpringCloud中也有对应的解决方案,SpringCloud Bus 将分布式的节点用轻量的消息代理连接起来,可以很容易搭建消息总线,配合SpringCloud config 实现微服务应用配置信息的动态更新。

    Spring Cloud之(二十)SpringCloud Config
    根据此图我们可以看出利用Spring Cloud Bus做配置更新的步骤:
    1. 提交代码触发post请求给bus/refresh
    2. server端接收到请求并发送给Spring Cloud Bus
    3. Spring Cloud bus接到消息并通知给其它客户端
    4. 其它客户端接收到通知,请求Server端获取最新配置
    5. 全部客户端均获取到最新的配置
  • 消息总线整合配置中心
  1. 引入依赖
    <!-- 消息总线 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-bus</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
    </dependency>
               
  2. 服务端配置

    application.yml

    server:
      port: 10006
    spring:
      application:
        name: ebuy-configServer
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/silent-sparrow/ebuy-config-server.git #git服务地址
      rabbitmq:
        host: 127.0.0.1
        port: 5672
        username: guest
        password: guest
    #配置集群(Eureka Client)
    eureka:
      client:
        healthcheck: true #开启健康检查(依赖spring-boot-actuator)
        service-url:
          defaultZone: http://127.0.0.1:9000/eureka/,http://127.0.0.1:8000/eureka/ #配置集群
      instance:
        prefer-ip-address: true #使用ip地址注册
        lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认是90秒)
        lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               
  3. 微服务客户端配置

    bootstrap.yml

    #配置集群(Eureka Client)
    eureka:
      client:
        healthcheck: true #开启健康检查(依赖spring-boot-actuator)
        service-url:
          defaultZone: http://127.0.0.1:9000/eureka/,http://127.0.0.1:8000/eureka/ #配置集群
      instance:
        prefer-ip-address: true #使用ip地址注册
        lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认是90秒)
        lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔
    spring:
      cloud:
        config:
          name: product #远程git中以product开头的配置文件
          profile: dev
          label: master
          discovery:
            enabled: true
            service-id: ebuy-configServer #远程git地址中的仓库名(配置中心)
    management:
      endpoints:
        web:
          exposure:
            include: '*'
               
  4. 在Gitee上修改对应的配置信息
    Spring Cloud之(二十)SpringCloud Config
    Spring Cloud之(二十)SpringCloud Config
    Spring Cloud之(二十)SpringCloud Config
    如果客户端有上百甚至上千个服务时,我们不可能每次都去对客户端提交请求,所以可以利用消息总线对配置中心发送对应的请求,即可刷新每个客户端的配置。

继续阅读