《深入理解 Spring Cloud 与微服务构建》第十三章 配置中心 Spring Cloud Config

文章目录

  • 《深入理解 Spring Cloud 与微服务构建》第十三章 配置中心 Spring Cloud Config
  • 一、Config Server 从本地读取配置文件
    • 1.构建 Config Server
    • 2.构建 Config Client
  • 二、Config Server 从远程 Git 仓库读取配置文件
  • 三、构建高可用的 Config Server
    • 1.构建 Eureka Server
    • 2.改造 Config Server
    • 3.改造 Config Client
  • 四、使用 Spring Cloud Bus 刷新配置
  • 五、将配置存储在 MySQL 数据库中
    • 1.改造 config-server 工程
    • 2.初始化数据库

一、Config Server 从本地读取配置文件

Config Server 可以从本地仓库读取配置文件,也可以从远程 Git 仓库读取。本地仓库是指将所有的配置文件统一写在 Config Server 工程目录下。Config Server 暴露 HTTP API 接口,Config Client 通过调用 Config Server 的 HTTP API 接口来读取配置文件

本案例和之前的工程一样,采用多 Module 形式。需要新建一个主 Maven 工程,在 pom 文件中指定 Spring Boot 的版本为 2.1.0,Spring Colud 的版本为 Greenwich.RELEASE

1.构建 Config Server

在主 Maven 工程下,创建一个 Module 工程,工程名取为 config-server,其 pom 文件继承主 Maven 工程的 pom 文件,并在 pom 文件中引入 Config Server 的起步依赖 spring-cloud-config-server。pom 文件代码如下:

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

在程序的启动类 ConfigServerApplication 加上 @EnableConfigServer 注解,开启 Config Server 的功能,代码如下:

package com.sisyphus;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 中做相关的配置,包括指定程序名为 config-server,端口号为 8769.通过 spring.profile.active=native 来配置 Config Server 从本地读取配置,读取配置的路径为 classpath 下的 shared 目录。application.yml 的配置文件的代码如下:

server:port: 8769spring:cloud:config:server:native:search-locations: classpath:/sharedprofiles:active: nativeapplication:name: config-server

在工程的 Resources 目录下建一个 shared 文件夹,用于存放本地配置文件。在 shared 目录下,新建一个 config-client-dev.yml 文件,用作 config-client 工程的 dev(开发环境)的配置文件。在 config-client-dev.yml 配置文件中,指定程序的端口号为 8762,并定义一个比哪里 foo,该变量的值为 foo version 1,代码如下:

server:port: 8762
foo: foo version 1

2.构建 Config Client

新建一个工程,取名为 config-client,该工程作为 Config Client 从 Config Server 读取配置文件,该工程的 pom 文件继承了主 Maven 工程的 pom 文件, 并在其 pom 文件引入 Conig 的起步依赖 spring-cloud-starter-config 和 WEB 功能的起步依赖 spring-boot-starter-web,代码如下:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency>
</dependencies>

在其配置文件 bootstrap.yml 中做程序的配置,注意这里用的是 bootstrap.yml,而不是 application.yml,bootstrap 相对于 application 具有优先的执行顺序。在 bootstrap.yml 配置文件中指定了程序名为 config-client,向 Url 地址为 http://localhost:8769 的 Config Server 读取配置文件。如果没有读取成功,则执行快速失败(fail-fast),读取的是 dev 文件。bootstrap.yml 配置文件中的变量 {spring.application.name} 和变量 {spring.profiles.active},两者以 “-” 相连,构成了向 Config Server 读取的配置文件名,所以本案例在配置中心读取的配置文件名为 cofig-client-dev.yml 文件。配置文件 bootstrap.yml 的代码如下:

spring:application:name: config-clientcloud:config:uri: http://localhost:8769fail-fast: trueprofiles:active: dev

config-server 工程启动成功后,启动 config-client 工程,你会在控制台的日志中发现 config-client 向 Url 地址为 http://localhost:8769 的 Config Server 读取了配置文件。最终程序启动的端口为 8762,这个端口是在 config-server 的 Resources/shared 目录中的 config-client-dev.yml 的配置文件中配置的,可见 config-client 成功地向 config-server 读取了配置文件

为了进一步验证,在 config-client 工程写一个 API 接口,读取配置文件的 foo 变量,并通过 API 接口返回,代码如下:

package com.sisyphus;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@SpringBootApplication
@RestController
public class ConfigClientApplication {public static void main(String[] args) {SpringApplication.run(ConfigClientApplication.class, args);}@Value("${foo}")String foo;@RequestMapping("/foo")public String hi(){return foo;}
}

打开浏览器,访问 http://localhost:8762/foo,浏览器显示:

foo version 1

可见 config-client 工程成功地向 config-server 工程读取了配置文件中的 foo 变量的值

二、Config Server 从远程 Git 仓库读取配置文件

Spring Cloud Config 支持从远程 Git 仓库读取配置文件,即 Config Server 可以不从本地的仓库读取,而是从远程 Git 仓库读取。这样做的好处是将配置哦统一管理,并且可以通过 Spring Cloud Bus 在不人工启动程序的情况下对 Config Client 的配置进行刷新。本例采用 Gitee 作为远程 Git 仓库

首先,修改 Config Server 的配置文件 application.yml,代码如下:

server:port: 8769spring:cloud:config:server:git:uri: https://gitee.com/jiang-qi-313YPHU3/spring-cloud-configsearchPaths: respousername: password: label: masterapplication:name: config-server

其中,uri 为远程 Git 仓库的地址,searchPaths 为搜索远程仓库的文件夹地址,username 和 password 为 Git 仓库的登录名和密码。如果是私人 Git 仓库,登录名和密码是必需的;如果是公开的 Git 仓库,可以不需要。label 为 git 仓库的分支名,本例从 master 读取

将上一节的 config-client-dev.yml 上传到远程仓库中,上传的路径为 https://gitee.com/jiang-qi-313YPHU3/spring-cloud-config,读者可以创建自己的仓库进行上传

重新启动 config-server,config-server 启动成功后,启动 config-client,可以发现 config-client 的端口为 8762.像上一节一样,访问 http://localhost:8762/foo,浏览器显示:

可见,config-server 从远程 Git 仓库读取了配置文件,config-client 从 config-server 读取了配置文件

三、构建高可用的 Config Server

当服务实例很多时,所有的服务实例需要同时从配置中心 Config Server 读取配置文件,这时可以考虑将配置中心 Config Server 做成一个微服务,并且将其集群化,从而达到高可用。Config Server 和 Config Clinet 向 Eureka Server 注册,并且将 Config Server 多实例集群部署

1.构建 Eureka Server

新建一个 eureka-server 工程,eureka-server 工程的 pom 文件继承了主 Maven 的 pom 文件, eureka-server 工程的 pom 文件引入 Eureka Server 的起步依赖 spring-cloud-starter-netflix-eureka-server 和 WEB 功能的起步依赖 spring-boot-starter-web,配置代码如下:

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

在工程的配置文件 application.yml 中做程序的相关配置,指定程序的端口号为 8761,代码如下:

server:port: 8761eureka:client:register-with-eureka: falsefetch-registry: falseserviceUrl:defaultZone: http://localhost:${server.port}/eureka/

在程序的启动类 EurekaServerApplication 上加 @EnableEurekaServer 注解,开启 Eureka Server 的功能,代码如下:

package com.sisyphus;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

2.改造 Config Server

Config Server 作为 Eureka Client,需要在工程中的 pom 文件引入 spring-cloud-starter-netflix-eureka-client 起步依赖,代码如下:

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

在工程的启动类 ConfigServerApplication 加上 @EnableEurekaClient 注解,开启 EurekaClient 的功能

在工程的配置文件 application.yml 文件中制定服务注册的地址,代码如下:

eureka:client:serviceUrl:defaultZone: http://locallhost:8761/eureka/

3.改造 Config Client

和 Config Server 一样作为 Eureka Client,在 pom 文件加上 spring-cloud-starter-netflix-eureka-client
起步依赖,在工程的启动类加上 @EnableEurekaClient 注解,开启 EurekaClient 的功能

在工程的配置文件 application.yml 加上相关配置,指定服务注册中心的地址为 http://localhost:8761/eureka/,向 Service Id 为 config-server 的配置服务读取配置文件,代码如下:

server:port: 8762spring:application:name: config-clientcloud:config:fail-fast: truediscovery:enabled: trueservice-id: config-serverprofiles:active: deveureka:client:serviceurl:defaultZone: http://localhost:8761/eureka/

依次启动 eureka-server、config-server 和 config-client 工程,注意这里需要 config-server 启动成功并且向 eureka-server 注册完成后,才能启动 config-client,否则 config-client 找不到 config-server

通过控制台可以发现,config-client 向地址为 http://localhost:8769 的 config-server 读取了配置文件。访问 http://localhost:8762/foo,浏览器显示:

foo version 2

可见,config-server 从远程 Git 仓库读取了配置文件,config-client 从 config-server 读取了配置文件

那么如何搭建高可用的 Config Server 呢?只需要将 Config Server 多实例部署,用 IDEA 开启多个 Config Server 实例,端口分别为 8769 和 8768。在浏览器上访问 Eureka Server 的主页 http://localhost:8761/,界面如图所示:

多次启动 config-client 工程,从控制台可以发现它会轮流地从 http://localhost:8768 和 http://localhost:8769 的 Config Server 读取配置文件,并做了负载均衡

四、使用 Spring Cloud Bus 刷新配置

Spring Cloud Bus 是用轻量的消息代理将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。一个关键的思想就是,消息总线可以为微服务做监控,也可以实现应用程序之间相互通信。Spring Cloud Bus 可选的消息代理组件包括 RabbitMQ、AMQP 和 Kafka 等。本节讲述的是用 RabbitMQ 作为 Spring Cloud 的消息组件去刷新更改微服务的配置文件

为什么需要用 Spring Cloud Bus 去刷新配置?

如果有几十个微服务,而每一个服务又是多实例,当更改配置时,需要重新启动多个微服务实例,会非常麻烦。Spring Cloud Bus 的一个功能就是让这个过程变得简单,当远程 Git 仓库的配置更改后,只需要向某一个微服务实例发送一个 Post 请求,通过消息组件通知其它微服务实例重新拉取配置文件。当远程 Git 仓库的配置更改后,通过发送 “/bus/refresh” Post 请求给某一个微服务实例,通过消息组件,通知其它微服务实例,更新配置文件

本节是在上一节的例子基础上进行改造的,首先,需要在 config-server 和 config-client 的 pom 文件中引入用 RabbitMQ 实现的 Spring Cloud Bus 的起步依赖 spring-cloud-starter-bus-amqp。如果读者需要自己实践,则需要安装 RabbitMQ 服务器。pom 文件添加的依赖如下:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

在 config-server 和 config-client 工程的配置文件 application.yml 添加 RabbitMQ 的相关配置,host 为 RabbitMQ 服务器的 IP 地址,port 为 RabbitMQ 服务器的端口,username 和 password 为 RabbitMQ 服务器的用户名和密码:

spring:rabbitmq:host: localhostport: 15672username: guestpassword: guestmanagement:endpoints:web:exposure:include: bus-refresh

最后,需要 config-client 在启动类上加 @RefreshScope 注解,只有加上了该注解,才会在不重启服务的情况下更新配置,如本例中更新配置文件 foo 变量的值,代码如下:

package com.sisyphus;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@SpringBootApplication
@RestController
@EnableEurekaClient
@RefreshScope
public class ConfigClientApplication {public static void main(String[] args) {SpringApplication.run(ConfigClientApplication.class, args);}@Value("${foo}")String foo;@RequestMapping("/foo")public String hi(){return foo;}
}

依次启动工程,其中 config-client 开启两个实例,端口分别为 8762 和 8763.启动完成后,在浏览器上访问 http://localhost:8762/foo 或者 http://localhost:8763/foo,浏览器显示:

foo version 2

更改远程 Git 仓库,将 foo 的值改为 “foo version 3”。通过 Postman 或者其他工具发送一个 Post 请求 http://localhost:8769/actuator/bus-refresh,请求发送成功,再访问 http://localhost:8762/foo 或者 http://localhost:8763/foo,浏览器会显示:

foo version 3

可见,通过向 8762 端口的微服务实例发送 Post 请求 http://localhost:8762/actuator/bus-refresh,请求刷新配置,由于使用了 Spring Cloud Bus,其他服务实例会接收到刷新配置的消息,也会刷新配置。另外,“/actuator/bus-refresh” API 接口可以指定服务,即使用 “destination” 参数,例如 “/actuator/bus-refresh?destination=eureka-client:**”,即刷新服务名为 eureka-client 的所有服务实例

五、将配置存储在 MySQL 数据库中

在大多数情况下,我们将配置存储在 Git 仓库中,即可满足业务需求。Spring Cloud Config 没有页面展示的功能,当我们需要二次开发对配置进行展示和做管控功能时,将配置存储在关系型数据库 MySQL 中可能会更便捷

本节的案例分为 config-server 和 config-client 两部分。其中,config-server 工程需要连接 MySQL 数据库,读取配置;config-client 则是在启动时从 config-server 工程读取。工程的创建过程参考本章第一节

1.改造 config-server 工程

在 config-server 工程的 pom 文件下引入 config-server 的起步依赖、mysql 的连接器、jdbc 的起步依赖,代码如下:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

在 config-server 工程的配置文件 application.yml 下做以下配置:

server:port: 8769spring:profiles:active: nativeapplication:name: config-serverdatasource:url: jdbc:mysql://127.0.0.1:3306/config-server ?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&serverTimezone=GMT&2B8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivercloud:config:label: masterserver:jdbc:sql: SELECT key1, value1 from config_properties where APPLICATION=? and PROFILE=? and LABEL=?

其中,spring.profiles.active 为 spring 读取的配置文件名,从数据库中读取,必须为 jdbc。spring.datasource 配置了数据库相关的信息,spring.cloud.config.label 读取配置的分支,这需要在数据库中与数据对应,本案例中为 master。spring.cloud.config.server.jdbc.sql 为查询数据库的 sql 语句,该语句的查询字段必须与数据库的表字段一致

2.初始化数据库

由于 config-server 使用的是数据库存储配置,因此读者需要先安装 MySQL 数据库。安装成功后,创建数据库名为 config-server 的数据库,数据库编码为 utf-8,然后在 config-server 数据库下执行以下数据库脚本:

CREATE TABLE `config_properties` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`key1` varchar(50) COLLATE utf8_bin NOT NULL,`value1` varchar(500) COLLATE utf8_bin DEFAULT NULL,`application` varchar(50) COLLATE utf8_bin NOT NULL,`profile` varchar(50) COLLATE utf8_bin NOT NULL,`label` varchar(50) COLLATE utf8_bin DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

其中,key1 字段为配置的 key1,value1 字段为配置的值,application 字段对应于应用名,profile 对应于环境,label 对应于读取的分支,一般为 master

插入数据 config-client 的 2 条数据包括 server.port 和 foo 两个配置,具体数据库脚本如下:

insert into `config_properties` (`id`, `key1`, `value1`, `application`, `profile`, `label`) values('1','server.port','8083','config-client','dev','master');
insert into `config_properties` (`id`, `key1`, `value1`, `application`, `profile`, `label`) values('2','foo','bar-jdbc','config-client','dev','master');

依次启动 config-server 和 config-client 两个工程,其中 config-client 的启动端口为 8083,这是在数据库中配置的,可见 config-client 从 config-server 中读取了配置。在浏览器上访问 http://localhost:8083/foo,浏览器显示 bar-jdbc,由此可见 config-client 从 config-server 中成功读取了配置,而配置是存储在数据库中的

《深入理解 Spring Cloud 与微服务构建》第十三章 配置中心 Spring Cloud Config相关推荐

  1. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  2. 《深入理解 Spring Cloud 与微服务构建》第十章 路由网关 Spring Cloud Zuul

    <深入理解 Spring Cloud 与微服务构建>第十章 路由网关 Spring Cloud Zuul 文章目录 <深入理解 Spring Cloud 与微服务构建>第十章 ...

  3. 《深入理解 Spring Cloud 与微服务构建》第九章 熔断器 Hystrix

    <深入理解 Spring Cloud 与微服务构建>第九章 熔断器 Hystrix 文章目录 <深入理解 Spring Cloud 与微服务构建>第九章 熔断器 Hystrix ...

  4. 《深入理解 Spring Cloud 与微服务构建》第二章 微服务应该具备的功能

    <深入理解 Spring Cloud 与微服务构建>第二章 微服务应该具备的功能 文章目录 <深入理解 Spring Cloud 与微服务构建>第二章 微服务应该具备的功能 一 ...

  5. 《深入理解 Spring Cloud 与微服务构建》第一章 微服务简介

    <深入理解 Spring Cloud 与微服务构建>第一章 微服务简介 文章目录 <深入理解 Spring Cloud 与微服务构建>第一章 微服务简介 一.单体架构及其存在的 ...

  6. 《深入理解Spring Cloud与微服务构建》出版啦!

    作者简介 方志朋,毕业于武汉理工大学,CSDN博客专家,专注于微服务.大数据等领域,乐于分享,爱好开源,活跃于各大开源社区.著有<史上最简单的Spring Cloud教程>,累计访问量超过 ...

  7. 《深入理解 Spring Cloud 与微服务构建》第十七章 使用 Spring Cloud OAuth2 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十七章 使用 Spring Cloud OAuth2 保护微服务系统 文章目录 <深入理解 Spring Cloud 与微服务构 ...

  8. 《深入理解 Spring Cloud 与微服务构建》第十六章 Spring Boot Security 详解

    <深入理解 Spring Cloud 与微服务构建>第十六章 Spring Boot Security 详解 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...

  9. 《深入理解 Spring Cloud 与微服务构建》第十五章 微服务监控 Spring Boot Admin

    <深入理解 Spring Cloud 与微服务构建>第十五章 微服务监控 Spring Boot Admin 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...

最新文章

  1. web 服务发布注意事项
  2. Java将Unix时间戳转换成指定格式日期
  3. 重写HttpServlet
  4. Windows Server 2016-Powershell迁移FSMO角色
  5. mysql explain 解释
  6. python中冒号报错_python新手常见错误和异常
  7. rsync+lsyncd实现(本地以及远程)文件实时同步
  8. hive求差集和交集
  9. java swing panel问题_关于 Java swing Box 的使用问题
  10. php过滤多空格_php正则过滤html标签、空格、换行符的代码(附说明)
  11. linux两台服务器传输,Linux两台服务器之间高速数据传输命令:scp应用详解
  12. PADS 设置挖空区域,为板子做固定孔,再设置禁止区域,铺铜之前必做的一步...
  13. 【数论】四则运算的取模处理
  14. lte基站信号测试软件,LTE基站的RF一致性测试
  15. Excel如何批量为员工信息表添加照片
  16. 踩坑 微信小程序开发mpvue使用iconfont,顺便解决偶现图标显示不正确
  17. Leetcode 1218. 最长定差子序列(DAY 47) ---- 动态规划学习期(昨天又没有看书捏 懒狗biss)
  18. 4、Arduino_esp32 ADC使用
  19. Android 仿余额宝数字动画实现
  20. 博士申请 | 香港科技大学陈浩老师招收人工智能医疗方向全奖博士/博后

热门文章

  1. 逆波兰计算器android源码简书,汪都能理解的逆波兰计算器(C++实现)
  2. webform快速创建表单内容文件--oracle 数据库
  3. C语言strcat()库函数的实现
  4. 软件測试之独步武林系列(一)
  5. AntiXSS v4.0中Sanitizer.GetSafeHtmlFragment等方法将部分汉字编码为乱码的解决方案
  6. oracle权限的分配
  7. KlayGE C++代码风格指南英文版
  8. 如何从课堂与教学内容两方面提高培训效率------张孝祥
  9. 转:C++反汇编揭秘2 – VC编译器的运行时错误检查(RTC)
  10. 龙芯笔记本可能以闹剧收场