服务配置——SpringCloud Config分布式配置中心

一、概述

1.1 分布式系统面临的—-配置问题

    1. 我们的模块越来越多,每个模块都要写一个application.yml。 我们想象这样一种情况: 10个微服务都要连接同一个数据库,我们在这10个微服务都配置了连接数据库yml。 当这个数据库发生了变化,怎么办? 修改10个yml。 如果是100个微服务都连接这个数据库呢? 东西多了,就要有统一个管理。
    1. 上线后,发布版本了。有生产环境,有测试环境,预发布版本环境。 那么就是3套的配置的管理系统和业务要求,一个配置文件不能同时满足三种环境。
    1. 集中式的管理这些配置。微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会 出现大量的服务。 由于每个服务都需要必要的配置信息才能运行,所以一套集中式,动态的配置管理设施是必不可少的。 我们每个微服务自己带着一个application.yml,上百个配置文件的管理… SpringCloud提供了ConfigServer来解决这个问题。

      1.2 Config是什么

      5. 服务配置&服务总线 - 图1
      SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持(Git/GitHub)(意思就是可以配置远程的配置文件?),配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置(Config Server)。
      统一共用的放在配置中心,各自特有的再单独配置。
      官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/
      由于SpringCloud Config默认使用Git来存储配置文件,最推荐与github整合。

      1.3 怎么用

      SpringCloud Config 分为服务端和客户端两部分。

服务端也称为分布式配置中心,他是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密等信息访问接口。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样既有助于对环境配置进行版本管理,并且可以通过git客户端来方便的管理和访问配置内容。

1.4 能干嘛

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新,分环境部署比如 dev/test/prod/beta/release
  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务回想配置中心统一拉取配置自己的信息。
  • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置。
  • 将配置信息以Rest接口的形式暴露。
  • 与GitHub整合配置,由于SpringCloud Config默认使用Git来存储配置文件,虽然也支持SVN。但是最推荐的还是 Git,而且使用的是http/https访问的形式。

https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/

二、 Config服务端配置与测试

2.1 用你自己的账号在GitHub上新建一个名为springcloud-config的新Repository

Repository中创建以下文件:
image.png
该文件可以从周阳老师的github仓库克隆一份,复制到自己的仓库 https://github.com/zzyybs/springcloud-config

2.2 由上一步获得刚新建的git地址

SSH:git@github.com:Bear-Lx/springcloud-config.git
Https:https://github.com/Bear-Lx/springcloud-config.git (推荐)

2.3 本地硬盘目录上新建git仓库并clone

我创建的仓库在:H:\SpringCloud2020 在此右键鼠标,点击Git Bash Here
注意:现在git clone命令进行clone时需要验证个人访问令牌,个人访问令牌的设置
image.png
image.png
表示多个环境的配置;保存格式必须是utf-8
如果需要对本地仓的文件进行了修改,同步到远程仓库,此处模拟运维人员操作git和github

git add git commit -m “init yml” git push origin master

2.4 新建Module模块 cloud-config-center-3344,它就是Cloud的配置中心模块 cloudConfig Center

image.png

2.5 pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>jdk8cloud2021</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-config-center-3344</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <!--springCloud Config Server-->
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-config-server</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-web</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-actuator</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-devtools</artifactId>
  37. <scope>runtime</scope>
  38. <optional>true</optional>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.projectlombok</groupId>
  42. <artifactId>lombok</artifactId>
  43. <optional>true</optional>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.springframework.boot</groupId>
  47. <artifactId>spring-boot-starter-test</artifactId>
  48. <scope>test</scope>
  49. </dependency>
  50. </dependencies>
  51. </project>

2.6 yml

  1. server:
  2. port: 3344
  3. spring:
  4. application:
  5. name: cloud-config-center #注册进Eureka服务器的微服务名
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: https://github.com/Bear-Lx/springcloud-config.git #GitHub上面的git仓库名字 这里可以写https地址跟ssh地址,https地址需要配置username和password
  11. default-label: main
  12. ####搜索目录
  13. search-paths:
  14. - springcloud-config
  15. ####读取分支
  16. label: main # 以前是master
  17. #服务注册到eureka地址
  18. eureka:
  19. client:
  20. service-url:
  21. # defaultZone: http://localhost:7001/eureka #单机版
  22. defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka #集群版

uri地址如果用https的别忘了配置username和password
注意这里cloud.config.server.git下面urisearch-paths以及label的含义
uri就是我们远程仓库的地址,search-paths表示远程仓库下有一个叫做springcloud-config的,label则表示读取master分支里面的内容(2020-10月开始master分支变为main分支)
新建的github分支已经默认为main,所以此处需指定 spring.cloud.config.server.git.default-label=main

2.7 主启动类

  1. package com.atguigu.springcloud;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.config.server.EnableConfigServer;
  5. @SpringBootApplication
  6. @EnableConfigServer //开启SpringCloud的
  7. public class ConfigCenterMain3344 {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ConfigCenterMain3344.class, args);
  10. }
  11. }

这里注意一下:我没有加@EnableEurekaClient注解,这个服务依然注册进eureka注册中心了。

原因:通过

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

依赖,可以省略@EnableEurekaClient,而根据yml配置文件想eureka里面注册。

2.8 测试

2.8.1 Https

使用https没有指明账号密码会报错:
image.png
指明账号密码访问成功:
image.png
image.png

2.8.2 SSH

这里应该使用 ssh-keygen -m PEM -t rsa -b 4096 -C "填自己的描述" 生成
ssh key
而不是使用 ssh-keygen -t rsa -C "填自己的描述" 生成ssh key
第一种方式生成的私钥是以BEGIN RSA PRIVATE KEY开头,END RSA PRIVATE KEY结尾;第二种方式生成的私钥是以BEGIN OPENSSH PRIVATE KEY开头,END OPENSSH PRIVATE KEY结尾,SpringCloud访问git的组件不支持openssh这种格式的密钥。
我没有测试SSH验证是否能够通过。
要么你仓库公开 就像老师这样,私有仓库的话uri可以换https然后配置帐号密码,或者依旧用ssh,然后多配个私钥都可以

2.8.3 映射规则

image.png
image.png

2.9 配置的读取规则

官网上有五种:
image.png
我们这里只讲常用的三种,其实都差不多

2.9.1 /{label}/{application}-{profile}.yml

image.png

读取main(master)分支

image.png

2.9.2 /{application}-{profile}.yml

默认去master分支找,所以这里不写分支
image.png
这里需要在yml文件中设置spring.cloud.config.server.git.default-label=main(github更新后master分支都成了main分支)
image.png

image.png

2.9.3 /{application}/{profile}[/{label}]

逆写法
image.png

得到的结果是Json字符串
image.png

2.10 总结

image.png
成功实现了SpringCloud通过GitHub获取配置信息

三、Config客户端配置与测试

上面我们的ConfigServer连接上了GitHub,成功的从GitHub上获取到了config信息
现在我们配置客户端,客户端从配置中心(Config Server)获取配置信息
image.png

3.1 新建cloud-config-client-3355

3.2 pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>jdk8cloud2021</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-config-client-3355</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <!--这里就是客户端的SpringCloud config 因为是客户端所以没有server-->
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-config</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  25. </dependency>
  26. <!--web/actuator这两个一般一起使用,写在一起-->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.boot</groupId>
  33. <artifactId>spring-boot-starter-actuator</artifactId>
  34. </dependency>
  35. <!--通用配置-->
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-devtools</artifactId>
  39. <scope>runtime</scope>
  40. <optional>true</optional>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.projectlombok</groupId>
  44. <artifactId>lombok</artifactId>
  45. <optional>true</optional>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-starter-test</artifactId>
  50. <scope>test</scope>
  51. </dependency>
  52. </dependencies>
  53. </project>

3344是server端所以依赖spring-cloud-starter-config-server后面有一个server,而3355定位是客户端,所以只有spring-cloud-starter-config

3.3 bootstrap.yml

为了配置文件的加载顺序和分级管理,我们这里使用boostrap.yml

  • application.yml是用户级的资源配置项
  • boostrap.yml是系统级的,优先级更高

Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment

要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的,因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml.
使用spring cloud 2020的同学 需要开启bootstrap支持 要加一个bootstrap的依赖,启动报错的引入spring-cloud-starter-bootstrap

  1. server:
  2. port: 3355
  3. spring:
  4. application:
  5. name: config-client
  6. cloud:
  7. #Config客户端配置
  8. config:
  9. label: main #分支名称 以前是master
  10. name: config #配置文件名称
  11. profile: dev #读取后缀名称 上述3个综合:main分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
  12. uri: http://localhost:3344 #配置中心地址k
  13. #服务注册到eureka地址
  14. eureka:
  15. client:
  16. service-url:
  17. defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka

image.png

3.4 主启动类

  1. package com.atguigu.springcloud;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. @SpringBootApplication
  6. @EnableEurekaClient
  7. public class ConfigClientMain3355 {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ConfigClientMain3355.class, args);
  10. }
  11. }

3.5 业务类

SpringCloud Config能够将配置信息以REST窗口的形式暴露

  1. package com.atguigu.springcloud.controller;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. public class ConfigClientController {
  7. @Value("${config.info}")
  8. private String configInfo;
  9. @GetMapping("/configInfo")
  10. public String getConfigInfo()
  11. {
  12. return configInfo;
  13. }
  14. }

3.6 测试

配置中心和客户端都注册进了eureka
image.png
image.png测试成功
成功实现了客户端3355访问SpringCloud Config3344通过GitHub获取配置信息
这里其他博主有出现问题SpringCloud-Config配置,参看博客上的解决办法,我并没有遇到相同的问题,直接成功。

3.7 问题随之而来——分布式配置的动态刷新问题

我们实现了客户端3355通过Config3344获取GithHub上的配置信息,那么现在面临另外一个问题:
Linux运维修改GitHub上的配置文件内容做调整
image.png
刷新3344,发现ConfigServer配置中心立刻响应
image.png
刷新3355,发现ConfigClient客户端没有任何响应
image.png3355没有变化除非自己重启或者重新加载,难到每次运维修改配置文件,客户端都需要重启??噩梦

四、Config客户端之动态刷新

避免每次更新配置都要重启客户端微服务3355,需要修改3355模块

4.1 pom引入actuator监控

一般我们在新建微服务模块的时候都会引入web跟actuator这两个依赖

  1. <!--web/actuator这两个一般一起使用,写在一起-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-actuator</artifactId>
  9. </dependency>

4.2 修改yml,暴露监控端口

image.png
2.0.0版本的SpringBoot的actuator启动端点监控web端默认加载默认只有两个info, health可见的页面节点。 如果需要显示更多需要在application.properties配置文件中添加 management.endpoints.web.exposure.include= management.endpoints.web.exposure.exclude=env,beans
include=
表示包含所有节点页面 ,exclude=env,beans 表示排除env、beans

4.3 在业务类上加一个@RefreshScope注解

  1. package com.atguigu.springcloud.controller;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.cloud.context.config.annotation.RefreshScope;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. @RefreshScope
  8. public class ConfigClientController {
  9. @Value("${config.info}")
  10. private String configInfo;
  11. @GetMapping("/configInfo")
  12. public String getConfigInfo()
  13. {
  14. return configInfo;
  15. }
  16. }

4.4 测试:3355还是没有动态刷新

发现GitHub上修改后,3355还是没有刷新
image.png

4.5 需要运维人员发送Post请求刷新3355

我们还需要让运维人员发送一下POST请求,刷新一下3355 必须是Post请求
curl -X POST “http://localhost:3355/actuator/refresh
image.png
发送post请求刷新后,客户端3355正常
image.png

4.6 多个微服务客户端,难道每个微服务都要手动刷新?

  • 在微服务多的情况下,每个微服务都需要执行一个post请求,手动刷新?
  • 可否广播,一次通知,处处生效? 大范围的实现自动刷新
  • 可能有这种情况:100台机器,有得不要求实时刷新。我们想实现该刷新的刷新,不想刷新的不刷新,怎么实现?

解决方法——Bus总线

服务消息总线——SpringCloud Bus

上一章我们讲了Config,其所能达到的极限也只是通过发送一个POST请求,手动版的实现动态刷新。 我们想解决这样的几个情形:

  • GitHub上的配置文件修改后,可否广播一下,不用每个微服务都通过发送POST请求动态刷新。
  • 可不可以该刷新的刷新,不想刷新的不刷新。

带着这些问题,我们来到本章Bus的学习,他是对Config的增强。
主要内容:

  1. 概述
  2. RabbitMQ环境配置
  3. SpringCloud Bus动态刷新全局广播
  4. SpringCloud Bus动态刷新顶点通知。

    1、概述

    1.1 是什么

    我们想实现分布式的自动刷新配置功能,不是通过手动发送POST请求实现刷新。 SpringCloudBus配合SpringCloudConfig使用可以实现配置的动态刷新。
    image.png
    配置更新后,将A刷新一下(推给A),然后通过总线“传染”给了其他的微服务。
    Bus支持两种消息代理:RabbitMQ和Kafka

    1.2 能干嘛

    Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道。
    image.png
    这里是推送给ConfigServer,跟上面推送给客户端是不一样的。

    1.3 为什么被称为总线

    什么是总线:在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
    基本原理:ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。

    2、RabbitMQ环境配置

    2.1 安装Erlang

    https://www.erlang-solutions.com/downloads/ 下载地址
    安装Erlang后会自动修改系统变量,但是需要重启系统才能生效。我们可以手动设置系统变量不重启。
    cmd中输入以下命令:
    C:\Users\Administrator>set ERLANG_HOME=H:\DevelopmentTools\erl-24.1 (自己的安装路径)
    或者是在系统环境变量中手动添加

    2.2 安装RabbitMQ

    https://rabbitmq.com/install-windows.html#installer
    进入RabbitMQ安装目录下的sbin目录:H:\DevelopmentTools\RabbitMQ Server\rabbitmq_server-3.9.7\sbin ,打开cmd输入如下命令:
    rabbitmq-plugins enable rabbitmq_management
    image.png
    这样就可以添加可视化插件了
    image.png
    以管理员身份启动start,不然会报错。然后测试是否安装成功:http://localhost:15672/ 账号密码都是guest。安装成功!
    image.png

    3、SpringCloud Bus动态刷新全局广播

    必须先具备良好的RabbitMQ环境

    3.1 Bus动态刷新全局广播的设计思想和选型

  • 1、利用消息总线出发一个客户端/bus/refresh,从而刷新所有客户端的配置

image.png

  • 2、利用消息总线接触一个服务端ConfigServer的/bus/refresh断点,从而刷新所有客户端的配置

image.png
图二的框架显然更合理一些,图一不适合的原因如下:

  1. 破坏了微服务的职责单一性,因为微服务本身是业务模块,它不应该承担配置刷新的功能
  2. 破坏了微服务各结点的对等性
  3. 有一定的局限性: 微服务迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就回增加更多的修改。

所以我们使用第二种:通知总线,总线再通知所有客户端。

3.2 添加一个新的cloud-config-client-3366

演示广播效果,增加复杂度,再以3355为模板再制作一个3366

3.2.1 pom

与3355相同

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>jdk8cloud2021</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-config-client-3366</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <!--这里就是客户端的SpringCloud config 因为是客户端所以没有server-->
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-config</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  25. </dependency>
  26. <!--web/actuator这两个一般一起使用,写在一起-->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.boot</groupId>
  33. <artifactId>spring-boot-starter-actuator</artifactId>
  34. </dependency>
  35. <!--通用配置-->
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-devtools</artifactId>
  39. <scope>runtime</scope>
  40. <optional>true</optional>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.projectlombok</groupId>
  44. <artifactId>lombok</artifactId>
  45. <optional>true</optional>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-starter-test</artifactId>
  50. <scope>test</scope>
  51. </dependency>
  52. </dependencies>
  53. </project>

3.2.2 yml

  1. server:
  2. port: 3366
  3. spring:
  4. application:
  5. name: config-client
  6. cloud:
  7. #Config客户端配置
  8. config:
  9. label: main #分支名称
  10. name: config #配置文件名称
  11. profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
  12. uri: http://localhost:3344 #配置中心地址
  13. #服务注册到eureka地址
  14. eureka:
  15. client:
  16. service-url:
  17. defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka
  18. # 暴露监控端点
  19. management:
  20. endpoints:
  21. web:
  22. exposure:
  23. include: "*"

3.2.3 主启动

  1. package com.atguigu.springcloud;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. @SpringBootApplication
  6. @EnableEurekaClient
  7. public class ConfigClientMain3366 {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ConfigClientMain3366.class, args);
  10. }
  11. }

3.2.4 业务类controller

  1. package com.atguigu.springcloud.controller;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.cloud.context.config.annotation.RefreshScope;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. @RestController
  7. @RefreshScope
  8. public class ConfigClientController {
  9. @Value("${server.port}")
  10. private String serverPort;
  11. @Value("${config.info}")
  12. private String configInfo;
  13. @GetMapping("/configInfo")
  14. public String configInfo()
  15. {
  16. return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;
  17. }
  18. }

分析

@Value(“${server.port}”)从配置文件中取前缀为server.port的值:注意这个模块关联了两个yml 一个是我们本地配置的bootstrap.yml,另一个是通过bootstrap.yml关联到3344,再关联到GitHub上的config-text.yml。所以@Value(“${server.port}”)从bootstrap.yml取到了server.port的值;@Value(“${config.info}”)从关联的config-{profile}.yml取到了info的值

3.3 配置案例

3.3.1 给cloud-config-center-3344配置中心服务端添加消息总线支持

pom:

  1. <!--添加消息总线RabbitMQ支持-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  5. </dependency>

yml: 注意对齐
image.png

  1. server:
  2. port: 3344
  3. spring:
  4. application:
  5. name: cloud-config-center #注册进Eureka服务器的微服务名
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: https://github.com/Bear-Lx/springcloud-config.git #GitHub上面的git仓库名字
  11. # uri: git@github.com:Bear-Lx/springcloud-config.git
  12. # uri 这里可以写https地址跟ssh地址,https地址需要配置username和password
  13. ####搜索目录
  14. search-paths:
  15. - springcloud-config
  16. username: Bear-Lx
  17. password: pangtou10086..
  18. default-label: main
  19. # skip-ssl-validation: true #
  20. ####读取分支
  21. label: main # 以前是master
  22. #rabbitmq相关配置
  23. rabbitmq:
  24. host: localhost
  25. port: 5672
  26. username: guest
  27. password: guest
  28. ##rabbitmq相关配置,暴露bus刷新配置的端点
  29. management:
  30. endpoints: #暴露bus刷新配置的端点
  31. web:
  32. exposure:
  33. include: 'bus-refresh'
  34. #服务注册到eureka地址
  35. eureka:
  36. client:
  37. service-url:
  38. # defaultZone: http://localhost:7001/eureka #单机版
  39. defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka #集群版

3.3.2 给cloud-config-client-3355客户端添加消息总线支持

pom:

  1. <!--添加消息总线RabbitMQ支持-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  5. </dependency>

yml:
image.png

3.3.3 给cloud-config-client-3366客户端添加消息总线支持

pom:

  1. <!--添加消息总线RabbitMQ支持-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  5. </dependency>

yml:
image.png

3.4 测试

启动7001、7002(我配了eureka集群)、3344、3355、3366
image.png
自测通过
image.png
修改GitHub上的配置文件,因为3355和3366都和config-dev.yml绑定,所以我们修改该配置文件,版本号修改成6
image.png
给3344Config-Server发送Post请求,刷新3344
curl -X POST "http://localhost:3344/actuator/bus-refresh"
image.png
image.png
一处刷新,处处生效!

基本原理回顾

ConfigClient实例都监听MQ中同一个topic(默认是SpringCloudBus)。 在RabbitMQ中找到了这个topic订阅主题/exchange路由交换机。
image.png
当一个服务刷新数据时,它会把这个信息放到Topic中,这样其他监听同一Topic的服务就能得到通知, 然后去更新自身的配置。

4、SpringCloud Bus动态刷新定点通知

只通知指定的微服务。比如:只通知3355,不通知3366,指定具体某一个实例生效,而不是全部。
公式:http://localhost:配置中心的端口号/actuator/bus-refresh/{destination},
/bus/refresh请求不再发送到具体的服务实例上,而是发给config server并通过destination参数类指定需要更新配置的服务或实例。

4.1 案例

我们这里以刷新运行在3355端口上的config-client为例,只通知3355,不通知3366
curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
image.png
成功:3355刷新,3366未刷新
image.png

5、流程总结

image.png