Spring Cloud - 配置中心

67 阅读4分钟

介绍

服务配置的现状:

在微服务系统中,每个微服务不仅仅只有代码,他还需要连接其他资源,例如数据库的配置或功能性的开关等;随着微服务系统的不断迭代,整个微服务系统可能成为一个网状结构,这时候就需要考虑整个微服务系统

的的扩展性、伸缩性、藕合性等;其中一个很重要的环节就是配置管理的问题;

常见的配置类型:

  • 服务配置
    • 数据库配置
    • 缓存配置
    • 消息队列配置
  • 开关配置
    • 功能开发
    • 业务开关
    • 服务开关
  • 业务配置
    • 模块A
    • 模块B

常用配置管理解决方案的缺点:

  • 硬编码
    • 需要修改代码,繁琐,风险大
  • 写在 properties 里面
    • 集群环境下,需要替换和重启
  • 写在 xml 配置文件中,一般和应用一起打包
    • 需要重新打包和重启

为什么要使用 spring cloud config 配置中心:

  • 由于常用的配置管理有很大的缺点,因此 spring cloud 采用了集中式的配置中心来管理每个服务的配置
  • 配置中心,在微服务和分布式系统中,采用服务端和客户端来提供可扩展的配置服务
  • 配置中心负责管理所有的服务的各种环境配置文件,配置服务中心默认采用 Git 的方式存储配置文件,因此我们很容易部署修改,有助于对环境配置进行版本管理

spring cloud config 配置中心,解决了什么问题:

配置中心解决了微服务配置的中心化、版本控制、平台独立、语言独立等问题

特性:

  • 提供服务端和客户端支持
  • 集中式管理分布式环境下的应用配置
  • 基于 Spring 环境,无缝与 Spring 应用集成
  • 可用于任何语言开发的程序
  • 默认实现基于 Git 仓库,可以进行版本管理

本地配置中心

服务端

引入依赖:

<!-- 配置中心 -->
<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>

配置 bootstrap.yml:

# 端口
server:
  port: 9100

# spring
spring:
  application:
    name: config
  profiles:
    active: native # 本地配置中心
# eureka
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

启动程序添加 @EnableConfigServer@EnableDiscoveryClient 注解:

注意

默认情况下,直接读取 classpath 目录下的配置,可以通过 spring.cloud.config.server.native.search-locations 重新指定本地读取路径;

classpath 下创建配置 provider-dev.properties:

# 应用名称
spring.application.name=provider
# 端口
server.port=8081
# 数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.name=defaultDataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/cmr-provider?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

# 注册中心
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
#eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/,http://127.0.0.1:8762/eureka/

客户端

引入依赖:

<!-- 配置加载 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置 bootstrap.yml:

spring:
  application:
    name: provider
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config
      profile: dev

启动程序添加 @EnableDiscoveryClient 注解;

说明:

客户端服务会从 config 配置中心,拉取名为 provider-dev.properties 的配置文件作为当前应用的配置信息;

远程配置中心

为了便于配置文件统一管理,并且可以进行版本控制,通常使用 Git 仓库作为配置仓库,客户端远程拉取配置信息;

服务端

# 端口
server:
  port: 9100

# spring
spring:
  application:
    name: config
  cloud:
    config:
      server:
        git: # 远程配置中心
          uri: https://gitee.com/zbcbbs/micro-service # Git 中配置仓库地址
          search-paths: /cloud/spring-cloud/cmr-config-repo # 仓库下相对地址 多个用 ',' 分隔
          username: zbcbbs
          password: xxxxxx
# eureka
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

图示:

image-20220817154005612

配置访问规则:

原理

图-4

配置刷新

全局刷新

图-5

服务端:

引入依赖:

<!-- 程序监控 -->        
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置刷新,基于 RabbitMq 消息总线 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置 bootstrap.yml:

# spring
spring:
  application:
    name: config
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    
# 全局配置刷新,支持访问 /actuator/bus-refresh
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
  endpoint:
    bus-refresh: true

客户端:

引入依赖:

<!-- 程序监控 -->        
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 配置刷新,基于 RabbitMq 消息总线 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

配置 bootstrap.yml:

spring:
  application:
    name: provider
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config
      profile: dev
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest

控制器上添加 @RefreshScope 注解,表示当前类涉及的配置信息可以自动刷新:

package com.dongzz.cmr.provider.controller;

import com.dongzz.cmr.provider.utils.ResponseVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 刷新配置
 *
 * @author zwk
 * @date 2022/8/17 19:26
 * @email zbcbbs@163.com
 */
@RestController
@CrossOrigin
@RefreshScope // 当前类涉及的配置信息,可以自动刷新
public class RefreshController {

    @Value("${refresh.version}")
    private String version;

    /**
     * 配置刷新测试
     */
    @GetMapping("/refresh")
    public String refresh() {
        return version;
    }
}

手动刷新:

POST 方式访问:http://localhost:9100/actuator/bus-refresh,`Content-Type` 需要设置为 application/json

自动刷新

当 Git 端配置发生变化,自动调用 /actuator/bus-refresh 接口

在 Git 仓库中配置 WebHooks,当推送配置到 Git 时,调用配置刷新接口,同步各个客户端的配置信息;

image-20211014214729894

客户端刷新

图-6

客户端

配置 bootstrap.yml:

spring:
  application:
    name: provider
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config
      profile: dev
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest

# 客户端配置刷新,支持访问 /actuator/bus-refresh
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
  endpoint:
    bus-refresh: true

刷新路径:

http://localhost:8081/actuator/bus-refresh

POST ,application/json 方式发起请求;