配置中心--Spring Cloud Config

目录

概述

环境说明

步骤

创建远端git仓库

准备配置文件

配置中心--服务端

配置中心--客户端

配置中心的高可用

配置中心--服务端

配置中心--客户端

消息总线刷新配置

配置中心--服务端

配置中心--客户端


概述

因为微服务架构有很多个服务,手动一个一个管理各个服务配置很麻烦,不同的环境(开发、测试、生产)往往需要不同的配置文件,运行期间也需要动态调整配置,修改配置后微服务需要自动更新配置,所以需要一个统一管理应用配置的组件。

配置中心是一种统一管理各种应用配置的基础服务组件。本文讲解的配置中心组件为Spring Cloud Config。

本文的操作可在 微服务调用链路追踪 的基础上进行 或者 在 Spring Cloud Stream实践 的基础上进行。

环境说明

jdk1.8

maven3.6.3

mysql8

spring cloud2021.0.8

spring boot2.7.12

idea2022

rabbitmq3.12.4

步骤

创建远端git仓库

创建远端git仓库,管理配置文件,使用gitee,创建仓库名称为config-repo(创建时点击创建README文件,方便直接用浏览器上传文件)

可使用远端仓库管理微服务公共的配置,而非公共的配置可放在各自微服务的application.yml中。

公共的配置,例如:数据库配置、Eureka配置等

非公共的配置,例如:端口号、应用名称等

准备配置文件

配置中心的配置文件命名规则为:

{application}-{profile}.yml
{application}-{profile}.properties

application为应用名称 profile指的开发环境(用于区分开发环境、测试环境、生产环境等)

复制product-serviceapplication.yml,重命名为application-pro.yml,抽取公共配置,例如:数据库配置、zipkin、sleuth、rabbitmq、eureka等,同时添加一个name属性(用于区别不同的环境配置),公共的配置放在远端git仓库。

application-pro.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
    generate-ddl: true #自动创建表
  zipkin:
    sender:
      type: rabbit #数据的传输方式,以rabbit的方式向server端发送数据
  sleuth:
    sampler:
      probability: 1 #采样比,日志的采样比例,默认0.1,测试环境设置为100%收集日志
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener: #这里配置重试策略
      direct:
        retry:
          enabled: true
      simple:
        retry:
          enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

logging:
  level:
    root: info
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG

name: product-pro

复制application-pro.yml得到application-dev.yml

application-dev.yml

配置内容如下,区别在于name的值为product-dev

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
    generate-ddl: true #自动创建表
  zipkin:
    sender:
      type: rabbit #数据的传输方式,以rabbit的方式向server端发送数据
  sleuth:
    sampler:
      probability: 1 #采样比,日志的采样比例,默认0.1,测试环境设置为100%收集日志
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener: #这里配置重试策略
      direct:
        retry:
          enabled: true
      simple:
        retry:
          enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

logging:
  level:
    root: info
    org.springframework.web.servlet.DispatcherServlet: DEBUG
    org.springframework.cloud.sleuth: DEBUG

name: product-dev

通过浏览器界面,手动上传application-pro.ymlapplication-dev.yml到git仓库

点击上传文件区域,选中需要上传的文件:application-pro.ymlapplication-dev.yml

 填写提交信息,点击提交

上传成功后,如下图

配置中心--服务端

创建子工程config_server

引入依赖

	<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    </dependencies>

启动类

package org.example.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer //开启配置中心服务端功能
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

配置application.yml

server:
  port: 11111
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/xxx/config-repo.git

uri的值是刚才创建的远端git仓库的地址,注意修改为自己的仓库地址。

启动config_server服务

浏览器访问

http://localhost:11111/application-dev.yml

访问不到数据

原因是gitee仓库是私有的,需要把仓库公开或者配置gitee的登录信息。

解决方法1:将git仓库开源

解决方法2:修改配置,加上gitee的用户名和密码

cloud:
  config:
    server:
      git:
        uri: https://gitee.com/xxx/config-repo.git
        username: xxx
        password: xxx

两种方法选择其中一个。

解决后,再次访问

http://localhost:11111/application-dev.yml

成功看到数据如下 

配置中心--客户端

配置中心客户端就是各个微服务

这里创建一个微服务:config_client_1

config_client_1项目结构如下

添加依赖

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--引入EurekaClient-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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>
        <!--消息总线bus-->
        <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>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

刷新依赖

非公共的配置application.yml

server:
  port: 9101
spring:
  application:
    name: config-client1

bootstrap.yml

spring:
  cloud:
    config:
      name: application #应用名称对应git配置文件的前半部分,例如:application-dev.yml,这里就写application
      profile: dev #开发环境
      label: master #git中的分支
      uri: http://localhost:11111 #config_server的请求地址

ConfigClientApplication.java

package org.example.config.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;

@SpringBootApplication
@EntityScan("org.example.config.client.entity.Product")
public class ConfigClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
}

Product.java

package org.example.config.client.entity;


import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;

/**
 * 商品实体类
 */
@Data
@Entity
@Table(name="tb_product")
public class Product {
    @Id
    private Long id;
    private String productName;
    private Integer status;
    private BigDecimal price;
    private String productDesc;
    private String caption;
    private Integer inventory;
}

ProductController.java

package org.example.config.client.controller;

import org.example.config.client.entity.Product;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/config-client/product")
public class ProductController {

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

    @RequestMapping("/get")
    public Product getProduct(){
        Product product = new Product();
        product.setProductName(name);
        return product;
    }
}

启动eureka、config_server、config_client_1服务

注意:因为远端git仓库的配置文件有eureka配置,所以拉取到配置后,需要启动eureka服务

浏览器访问

http://localhost:9101/config-client/product/get

响应
{"id":null,"productName":"product-dev","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

pruductName为product-dev,与git的application-dev.yml的name属性一致

config_client_1bootstrap.yml的profile改为pro

重启config_client_1服务

再次访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

 pruductName为product-pro,与git的application-pro.yml的name属性一致

修改git的配置

查看application-pro.yml文件,点击编辑

product-pro改为product-pro1 

点击提交

浏览器访问

http://localhost:9101/config-client/product/get

发现数据未更新,还是product-pro

解决方式:

方式一:重启config_client_1服务

发现重启可以拿到最新数据,但是,在生产环境中,重启服务有时候不太方便。

方式二:手动刷新

修改config_client_1服务

pom.xml,引入actuator依赖(之前已引入,跳过)

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

在需要的更新数据的类上添加@RefreshScope,开启动态刷新

修改bootstrap.yml

#开启动态刷新的端点
management:
  endpoints:
    web:
      exposure:
        include: refresh

重启config_client_1服务

访问

http://localhost:9101/config-client/product/get

productName是product-pro1

将git配置文件的name值修改为product-pro2

发起post请求刷新数据

curl -X POST "http://localhost:9101/actuator/refresh"

可使用postman或cmd命令行发起请求,这里使用cmd命令行发起post请求

再次访问

http://localhost:9101/config-client/product/get

响应最新的数据:product-pro2

手动刷新操作总结:

  1. 引入actuator依赖

  2. 需要的更新数据的类上添加@RefreshScope,开启动态刷新

  3. bootstrap.yml开启动态刷新的端点

  4. 修改git配置

  5. 发起post请求手动刷新数据

手动刷新能解决在不重启应用情况下,能做到动态刷新配置。但当服务很多时或需要更新的数据接口很多的情况下,就需要发起很多次Post请求,手动刷新显得很麻烦。可以使用消息总线技术解决该问题。

配置中心的高可用

一台配置中心服务容易出现单点故障问题,将配置中心集群化构成高可用的配置中心可以解决配置中心单点故障问题。

将多个配置中心注册到eureka,提供统一的服务名称,客户端通过服务名称调用配置中心。

配置中心--服务端

修改config_server服务

添加依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

刷新依赖

application.yml添加eureka相关配置

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka
    instance:
      prefer-ip-address: true
      instance-id: ${spring.cloud.client.ip-address}:${server.port}

修改config_server配置文件,添加default-label: master配置

cloud:
  config:
    server:
      git:
        uri: https://gitee.com/xxx/config-repo.git
        default-label: master

注意修改uri为自己git远端仓库地址。 

启动eureka、config_server服务

查看Eureka Web UI,看到了一台配置中心服务

http://localhost:9000/

通过复制配置方式,得到另外一台配置中心

修改端口号,复制运行配置,再启动一台配置中心服务

刷新查看Eureka Web UI,看到CONFIG-SERVER配置中心服务有两个实例。

配置中心--客户端

config_client_1服务

修改bootstrap.yml,添加eureka配置,修改通过服务名称(config-server)拿到配置

spring:
  cloud:
    config:
      name: application #应用名称对应git配置文件的前半部分,例如:application-dev.yml,这里就写application
      profile: pro #开发环境
      label: master #git中的分支
      #uri: http://localhost:11111 #config_server的请求地址
      discovery:
        enabled: true #开启服务发现
        service-id: config-server #配置服务的服务名称
#开启动态刷新的端点
management:
  endpoints:
    web:
      exposure:
        include: refresh

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka
    instance:
      prefer-ip-address: true
      instance-id: ${spring.cloud.client.ip-address}:${server.port}

重启config_client_1服务

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

能正常拿到数据,说明配置正常

高可用测试

测试关闭其中一个服务,是否还可以正常提供服务

再次访问

访问依然正常,说明实现了配置中心的高可用。

总结:

  1. 服务端,添加服务注册依赖及配置,注册到eureka中,开启两个服务。

  2. 客户端,添加eureka配置,使用服务名称获取配置

  3. 测试:断开一个服务,不影响访问

消息总线刷新配置

此前,通过发起Post请求手动刷新配置,服务接口很多时,就需要发起很多次Post请求,显得很麻烦。

通过消息总线刷新配置流程如下:

配置中心--服务端

config_server服务

添加依赖

		<!--消息总线依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

刷新依赖

配置application.yml

配置Spring Cloud Bus的RabbitMQ连接信息,启用Spring Cloud Bus(spring.cloud.bus.enabled=true默认已启动),同时暴露动态刷新的端点。

server:
  port: 11112
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/liang_123456/config-repo.git
          default-label: master
#    bus:
#      enabled: true
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest

#开启动态刷新的端点
management:
  endpoints:
    bus-refresh:
      enabled: true
    web:
      exposure:
        include: bus-refresh

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka
    instance:
      prefer-ip-address: true
      instance-id: ${spring.cloud.client.ip-address}:${server.port}

注意:开启动态刷新端点的management要顶格写

配置中心--客户端

spring-client_1服务

和config_server一样,添加依赖,如果已经存在就不用再添加

		<!--消息总线依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

刷新依赖

配置rabbitmq信息,因为是配置中心,所以在git远端仓库的配置文件配置即可,查看远端git配置文件,已经配置,如下

重启eureka、config_server和spring-client_1服务

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

修改git远端配置

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

响应product-pro2,说明还不是最新配置

发起Post请求, 刷新服务端配置

curl -X POST "http://localhost:11112/actuator/busrefresh"

注意:新版本发起post请求路径要改为busrefresh,而不是bus-refresh

访问

http://localhost:9101/config-client/product/get

响应
{"id":null,"productName":"product-pro3","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

响应的数据也是product-pro3,说明使用消息总线方式刷新配置成功。 


 

完成!enjoy it!

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
config-keeper是一个基于Spring Boot 和Spring Cloud开发的配置中心,无缝兼容Spring Boot 和 Spring Cloud应用。 在微服务架构中,配置中心是个必不可少的基础服务。应用部署到生产环境后,由于各种原因,需要调整一些配置。如果每次修改配置都需要经过修改代码、重新打包、重新部署等过程,为了避免重新部署造成请求错误,还需要将应用从负载均衡中下线,部署成功后再重新上线,当部署的实例比较多的情况下,那就会严重影响投产效率,如果是为了解决生产上的问题而调整配置,那么这个过程耗时越多,带来的风险也就越大。所以我们需要在不停机、不重新打包、不重新部署的情况下,可以动态修改配置(比如:功能开关、性能参数等)。为了方便动态更新应用配置,需要把配置放到应用执行包之外的配置中心。配置文件不需要打进应用执行包中后,可以带来以下几个好处:一个可执行包就可以在不同的环境下运行,可以降低包的版本管理成本,也可以降低docker镜像的版本管理成本。 Spring cloud 虽然已经为我们提供了基于git或mongodb等实现的配置中心,但是这些方案实现都过于简单,没有达到实际可用的标准,比如:没有提供统一的管理页面,不便于操作和使用;没有权限管理功能;没有数据验证功能等等。但Spring cloud config的核心技术还是可以为我们所有,没有必要重新造轮子。 ConfigKeeper 是由随行付架构部基于Spring Cloud研发的分布式配置中心。基于Spring Cloud开发。与Spring Boot、Spring Cloud应用无缝兼容。下面我们将详细介绍ConfigKeeper配置中心(有图有真像): 1. 支持权限管理,保证数据的安全 角色设计比较简单,只有管理员和普通用户两种,管理员拥有最高权限,而普通用户只能查看和操作为其分配的配置,以保证数据的安全。 2. 支持多环境部署,也支持多环境配置集中管理 企业可以根据自身的情况设置不同的环境,比如:测试、rc以及生产环境。可以多环境共用一个配置中心,也可以每个环境单独使用一个配置中心,根据企业需求灵活部署。 3. 配置管理简单实用 为了避免配置内容耦合问题,我们只设计了全局配置(global config)和应用配置(application config)两种类型的配置,并没有设计”组配置“。全局配置是指某一环境下所有应用都能生效的配置,但它的优先及低于应用配置,一个运行环境下有且只有一个全局配置。如果应用可执行包已经有相同的配置,那么会被配置中心的配置所覆盖。 3.1 自带版本管理功能:自动生成版本号以及回退功能 3.2 使用Yml在线编辑器,能实时检查配置格式是否正确; 3.3 支持修改前后内容对比功能,保证修改内容的正确性 4. 客户端使用简单并兼容Spring Boot和Spring Cloud应用 配置中心提供http接口拉取配置,所以只要支持http协议的应用都是可以使用的。我们已经实现了Spring Boot和Spring Cloud应用的客户端,接下来说明其一些特性及使用方法。 4.1 无缝兼容Spring boot、Spring Cloud应用 4.2 支持灰度发布 4.3 支持客户端缓存,即使配置中心服务不可用,也不会影响应用的启动

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值