demo结构
父工程:
子工程:
任务
用户微服务bill-service的配置文件存放在Git仓库中,想要实现:在gitee中修改该配置文件,bill-service不需要重启就能获取最新的配置文件信息。
注意:如果不使用Spring Cloud Bus + RabbitMQ,而只有Spring Cloud Config的话,只有重启用户微服务,才能获取最新的配置文件。
如有表述不当的地方,欢迎指正~
参考资料:RabbitMQ的下载与安装与启动
1.下载并安装erlang
因为RabbitMQ是基于erlang语言开发的,所以要安装erlang语言的开发环境
2.下载并安装RabbitMQ
3.启动RabbitMQ
打开命令行界面,进入到RabbitMQ安装包的sbin目录下,输入指令:
rabbitmq-plugins enable rabbitmq_management
4.浏览器地址栏输入localhost:15672,可以看到登录页面,密码与账户都是默认为:guest。然后就可以访问RabbitMQ可视化界面了。
添加依赖包: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>
添加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
添加依赖包: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>
添加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
在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的端口号列在这里,方便查看。
依次启动:(顺序别错了)
注册中心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消息总线服务,消息总线服务接收到请求后会向消息队列中发送消息,各个微服务会监听消息队列。当微服务接收到队列中的消息后,会重新从配置中心获取最新的配置信息。
发送请求后,立即查看RabbitMQ的可视化界面,可看到因为发送/接受消息而引起的一些变化。如Queues的Message rates,Overview里的两个图表。
最后,我们发送请求:http://127.0.0.1:8086/api/bill/1,在后端(bill-service的控制台)查看test.name的值。
后端打印的test.name值确实为配置文件中最新值,实现了配置文件实时更新!
还有个请求:http://localhost:12000/bill-dev.yml,作用是通过配置中心微服务config-server访问配置文件,在Git仓库改了配置文件后,发送该请求,显示的配置文件内容和Git仓库中的一致,说明config-server是可以实时地获取最新配置文件的,且不依赖于消息总线。而用户微服务实时获取最新配置文件是依赖于消息总线的。
这里总结下几个请求的作用:
基于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 实现配置中心配置动态更新