Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新

Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新

  • 概述
  • RabbitMQ的安装与启动
  • 改造配置中心微服务config-server
    • pom.xml依赖包引入
    • 配置文件application.yml
  • 改造用户微服务bill-service
    • pom.xml依赖包引入
    • 配置文件bootstrap.yml
    • Controller
  • 测试
  • 总结

概述

demo结构
父工程:

  • springcloud-billmanager

子工程:

  • 用户微服务:bill-service,端口号:9091
  • 配置中心微服务:config-server,端口号:12000
  • 网关:czn-gateway,端口号:8086
  • 注册中心:eureka-server,端口号:10086

任务
用户微服务bill-service的配置文件存放在Git仓库中,想要实现:在gitee中修改该配置文件,bill-service不需要重启就能获取最新的配置文件信息。

注意:如果不使用Spring Cloud Bus + RabbitMQ,而只有Spring Cloud Config的话,只有重启用户微服务,才能获取最新的配置文件。

如有表述不当的地方,欢迎指正~

RabbitMQ的安装与启动

参考资料:RabbitMQ的下载与安装与启动

1.下载并安装erlang
因为RabbitMQ是基于erlang语言开发的,所以要安装erlang语言的开发环境
2.下载并安装RabbitMQ
3.启动RabbitMQ
打开命令行界面,进入到RabbitMQ安装包的sbin目录下,输入指令:

rabbitmq-plugins enable rabbitmq_management

Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第1张图片

4.浏览器地址栏输入localhost:15672,可以看到登录页面,密码与账户都是默认为:guest。然后就可以访问RabbitMQ可视化界面了。

Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第2张图片

改造配置中心微服务config-server

pom.xml依赖包引入

添加依赖包:spring-boot-starter-actuator、spring-cloud-starter-bus-amqp、spring-cloud-bus、spring-cloud-starter-stream-rabbit ,这几个是实现配置文件实时更新需要的。


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-billmanagerartifactId>
        <groupId>com.czngroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>config-serverartifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-config-serverartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-busartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-stream-binder-rabbitartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-bus-amqpartifactId>
        dependency>
    dependencies>

project>

配置文件application.yml

添加RabbitMQ的配置信息,暴露触发消息总线的地址。

注意:浏览器访问RabbitMQ可视化界面时,使用的端口号是15672,而在配置文件中,使用的端口号是5672,不要弄混了。

server:
  port: 12000

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/chen-zuo-na/billmanager-config.git
  # 配置rabbitmq信息;如果是都与默认值一致则不需要配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

management:
  endpoints:
    web:
      exposure:
        # 暴露触发消息总线的地址
        include: bus-refresh

改造用户微服务bill-service

pom.xml依赖包引入

添加依赖包:spring-boot-starter-actuator、spring-cloud-starter-bus-amqp、spring-cloud-bus、spring-cloud-starter-stream-rabbit ,这几个是实现配置文件实时更新需要的。


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-billmanagerartifactId>
        <groupId>com.czngroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>bill-serviceartifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>tk.mybatisgroupId>
            <artifactId>mapper-spring-boot-starterartifactId>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>
        
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelper-spring-boot-starterartifactId>
            <version>1.2.3version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-configartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-busartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-stream-binder-rabbitartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-bus-amqpartifactId>
        dependency>
    dependencies>
project>

配置文件bootstrap.yml

添加RabbitMQ的配置信息。

为何用户微服务的配置文件叫做bootstrap.yml而不是application.yml?
我们已经把它的application.yml传到Git仓库里了,叫做bill-dev.yml。bootstrap.yml文件也是Spring Boot的默认配置文件,而且其加载的时间相比于application.yml更早,bootstrap.yml文件相当于项目启动时的引导文件,内容相对固定。application.yml文件是微服务的一些常规配置参数,变化比较频繁。

spring:
  cloud:
    config:
      # 要与仓库中的配置文件的application保持一致
      name: bill
      # 要与仓库中的配置文件的profile保持一致
      profile: dev
      # 要与仓库中的配置文件所属的版本(分支)一样
      label: master
      discovery:
        # 使用配置中心
        enabled: true
        # 配置中心服务名
        service-id: config-server
  # 配置rabbitmq信息;如果是都与默认值一致则不需要配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

Controller

在BillController类上加上注释:@RefreshScope 用于刷新配置

为了测试配置文件实时更新,我们将Git仓库里的配置文件添加一个属性:

test: # 用于测试配置文件的同步更新,spring cloud bus
    name: czn10

在Controller中增加一个name属性,通过注释@Value读取配置文件中的相应信息。
用户访问http://127.0.0.1:8086/api/bill/1时,通过网关gateway,路由到http://127.0.0.1:9091/bill/1,调用queryById方法,打印配置文件中的test.name的值。

Controller:

@RestController//不要写成@Controller!!!
//@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,返回json数据
//使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面
@RequestMapping("/bill")
@RefreshScope //配置文件改变,自动刷新,Spring cloud bus
public class BillController {
    @Autowired
    private TypeService typeService;

    @Autowired
    private BillService billService;

    @Value("${test.name}")//通过该注释读取配置文件中的信息
    private String name;//用于测试码云中配置文件的更新

    @GetMapping("/{id}")
    public Bill queryById(@PathVariable Long id){
        System.out.println("配置文件中的test.name为:"+name);//用于测试码云中配置文件的更新
        return billService.queryById(id);
    }}

Git仓库里的配置文件bill-dev.yml:

server:
  port: 9091

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/bill-manager
    username: root
    password:
  application:
    name: bill-service #指定应用名称,将来会作为应用的id使用

mybatis:
  type-aliases-package: com.czn.entity #别名搜索
  mapper-locations: classpath:/mybatis/*.xml

eureka:
  client:
    service-url:
      defaultZone: HTTP://127.0.0.1:10086/eureka
  instance:
    #默认注册时使用的是主机名或者localhost,如果想用ip进行注册,添加配置如下
    ip-address: 127.0.0.1 # ip地址
    prefer-ip-address: true # 更倾向于使用ip,而不是host名

test: # 用于测试配置文件的同步更新,spring cloud bus
    name: czn10

测试

把几个application的端口号列在这里,方便查看。

  • 用户微服务:bill-service,端口号:9091
  • 配置中心微服务:config-server,端口号:12000
  • 网关:czn-gateway,端口号:8086
  • 注册中心:eureka-server,端口号:10086

依次启动:(顺序别错了)
注册中心eureka-server -> 网关czn-gateway -> 配置中心微服务config-server -> 用户微服务bill-service

此时,我们去RabbitMQ可视化界面,点击Queues进行查看,可以看到有2个queue,实际上就是配置中心微服务config-server和用户微服务bill-server,如果配置文件改变,config-server给基于RabbitMQ的Spring Cloud Bus发送相关消息,bill-server由于一直监听着基于RabbitMQ的Spring Cloud Bus,就会收到消息,然后从config-server获取新的配置信息(即刷新配置)。可以搭配“总结”中的Spring Cloud结构图进行理解。

去Git仓库改test.name的值,改为:

test: # 用于测试配置文件的同步更新,spring cloud bus
    name: czn888

使用Postman给config-server发送请求,使用Post方法发送请求http://127.0.0.1:12000/actuator/bus-refresh,访问配置中心的Spring Cloud Bus消息总线服务,消息总线服务接收到请求后会向消息队列中发送消息,各个微服务会监听消息队列。当微服务接收到队列中的消息后,会重新从配置中心获取最新的配置信息。
Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第3张图片

发送请求后,立即查看RabbitMQ的可视化界面,可看到因为发送/接受消息而引起的一些变化。如Queues的Message rates,Overview里的两个图表。
Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第4张图片
Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第5张图片

最后,我们发送请求:http://127.0.0.1:8086/api/bill/1,在后端(bill-service的控制台)查看test.name的值。
Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第6张图片
在这里插入图片描述
后端打印的test.name值确实为配置文件中最新值,实现了配置文件实时更新!

还有个请求:http://localhost:12000/bill-dev.yml,作用是通过配置中心微服务config-server访问配置文件,在Git仓库改了配置文件后,发送该请求,显示的配置文件内容和Git仓库中的一致,说明config-server是可以实时地获取最新配置文件的,且不依赖于消息总线。而用户微服务实时获取最新配置文件是依赖于消息总线的。

这里总结下几个请求的作用:

  • http://127.0.0.1:8086/api/bill/1
    这个请求是发送给网关的,通过网关gateway路由到bill-service,调用queryById方法,控制台会打印配置文件中test.name的值
  • http://127.0.0.1:12000/actuator/bus-refresh
    这个请求是发送给配置中心微服务的,config-server接受到该请求后,会给消息总线发送消息,通知用户微服务:配置文件更改了。
  • http://localhost:12000/bill-dev.yml
    这个请求是发送给配置中心微服务的,通过config-server访问配置文件。

总结

Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置文件实时更新_第7张图片

基于RabbitMQ的Spring Cloud Bus是消息总线,配置中心微服务config-server是消息的提供者(给消息总线发送消息),用户微服务bill-server是消息的接受者(监听着消息总线,接收消息)。

如果配置文件改变,config-server会获取最新的配置文件(不依赖于消息总线)。config-server如果收到POST方式的/actuator/bus-refresh请求,就会给消息总线发送相关消息,通知用户微服务:配置文件发生了改变,bill-server由于一直监听着消息总线,就会收到消息,然后从config-server获取新的配置信息(即刷新配置)。

踩坑记录:
配置文件实时更新失败,查看RabbitMQ可视化界面的Queues,发现只有一个queue,对应config-server(是消息的提供者),即消息的接受者bill-server根本没监听到Spring Cloud Bus消息总线。直到阅读了下方的一篇文章,发现有依赖包少引入了,补齐依赖包后,就成功了。

如有表述不当的地方,欢迎指正~

这篇教程也可以参考下:Spring Cloud Config + Spring Cloud Bus + RabbitMQ 实现配置中心配置动态更新

你可能感兴趣的:(java,spring,rabbitmq,spring,cloud)