Spring Cloud Bus:
在分布式系统中,我们通常会使用轻量级的消息代理(rabbitmq、kafuka)建立一个公共的主题,让所有的微服务都链接进来,并且监听消费这个主题内的内容。我们就称这个主题是消息总线。 通过Spring Cloud Bus可以非常容易的搭建消息总线,同时实现一些消息总线中的常用功能,比如,结合Spring Cloud Config可以动态刷新微服务的应用配置信息,然后可以将其用于广播状态更改(例如,配置更改)或其他管理指令,Bus的基本结构思路如下:
实现原理:
1、ConfigServer(配置中心服务端)从远端git拉取配置文件并在本地git一份,ConfigClient(微服务)从ConfigServer端获取自己对应 配置文件;
2、当远端git仓库配置文件发生改变,ConfigServer如何通知到ConfigClient端,即ConfigClient如何感知到配置发生更新
Spring Cloud Bus会向外提供一个http接口,即图中的/bus/refresh。我们将这个接口配置到远程的git的webhook上,当git上的文件内容发生变动时,就会自动调用/bus-refresh接口。Bus就会通知config-server,config-server会发布更新消息到消息总线的消息队列中,其他服务订阅到该消息就会信息刷新,从而实现整个微服务进行自动刷新 如下图所示:
如上图所示 实现步骤如下:
1、提交配置触发post请求给server端的bus/refresh接口
2、server端接收到请求并发送给Spring Cloud Bus总线
3、Spring Cloud bus接到消息并通知给其它连接到总线的客户端
4、其它客户端接收到通知,请求Server端获取最新配置
5、全部客户端均获取到最新的配置
项目的搭建:
1.首先我们看到还是之前的项目 项目结构如下:
2.实现BUS的刷新,我们只需用到的项目为regedit ,config_module(作为服务端),system_module(作为客户端),regedit项目代码没有变化 这里就不做代码粘贴了 首先改动的config_module项目内容如下:
pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tone</groupId>
<artifactId>config_module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config_module</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--配置中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.bootstrap.yml内容:
server:
port: 8888
config:
regcenter:
ip: 127.0.0.1
prot: 8762
username: admin
password: 123456
servlet:
multipart:
max-file-size: 20MB
max-request-size: 100MB
#当前使用配置
spring:
application:
name: configCenter
profiles:
active: dev
# 配置中心
cloud:
config:
server:
git:
uri: https://gitee.com/hezhipeng_ek/tone_config.git
username: 15921363361
password: 123456
default-label: master
rabbitmq:
host: 192.168.142.128
port: 5672
username: guest
password: guest
eureka:
client:
register-with-eureka: true
fetch-registry: true
## 注册服务中心的配置
service-url:
defaultZone: http://${config.regcenter.username}:${config.regcenter.password}@${config.regcenter.ip}:${config.regcenter.prot}/eureka/
#开放actuator的bus-refresh端点
management:
endpoints:
web:
exposure:
include: "*"
注意如上git URL那里 之前我们用的是本地配置文件 这里我把它改为git配置文件了 首先在自己的码云gitee上建一个配置文件的项目,我建的如下:
3.以上config_module项目修改完成 system_module修改代码如下:
pom.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tone</groupId>
<artifactId>system_module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>system_module</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--配置中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
bootstrap.yml修改内容如下:
server:
port: 8080
spring:
application:
name: systemCenter
# dev环境
profiles:
active: dev
cloud:
config:
label: master
profile: dev
uri: http://localhost:8888
rabbitmq:
host: 192.168.142.128
port: 5672
username: guest
password: guest
config:
regcenter:
ip: 127.0.0.1
prot: 8762
username: admin
password: 123456
eureka:
client:
register-with-eureka: true
fetch-registry: true
## 注册服务中心的配置
service-url:
defaultZone: http://${config.regcenter.username}:${config.regcenter.password}@${config.regcenter.ip}:${config.regcenter.prot}/eureka/
#开放actuator的bus-refresh端点
management:
endpoints:
web:
exposure:
include: "*"
然后写一个获取system_module项目修改配置文件的测试方法 代码如下:
package com.tone.user.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope //bus实现刷新注解
public class ConfigController {
@Value("${config.db.ip}")
private String shoujin;
@GetMapping("/getInfo")
public String getInfo(){
return shoujin;
}
}
以上代码全部修改完成 依次启动项目regedit 、config_module、system_module三个项目 从而实现配置自动和手动刷新,需要调用/bus-refresh接口通知system_module 两种方式如下:
1.手动调用(post请求):首先我们在修改git上的配置后 不启动客户端项目的情况下 修改之前调用localhost:8080/getInfo接口 修改配置文件之后调用http://localhost:8888/actuator/bus-refresh接口 然后再调用localhost:8080/getInfo 三个调用接口如下所示:
2.配置git的webhook ,webhook在码云gitee上的配置在我上一篇文章有所提及到,还会遇到报400的报错 解决方法也有提及到,可以去看一下 当git端配置发生改变,自动调用/bus-refresh接口 因为是自动刷新了 所以这里不用再去调用那个http://localhost:8888/actuator/bus-refresh接口了 当修改配置之后 用git提交时 估计需要等个几秒钟 而 当代码发生改变后 webhook已经通知到bus了 所以我们这里只需要调用localhost:8080/getInfo接口看ip发生改变没即可 如下图: