Spring Cloud构建微服务架构(七)消息总线
先回顾一下,在之前的Spring Cloud Config的介绍中,我们还留了一个悬念:如何实现对配置信息的实时更新。虽然,我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Git仓库中的内容修改触发应用程序的属性更新。但是,若所有触发操作均需要我们手工去维护Web Hook中的应用位置的话,这随着系统的不断扩张,会变的越来越难以维护,而消息代理中间件是解决该问题最为合适的方案。是否还记得我们在介绍消息代理中的特点时有提到过这样一个功能:消息代理中间件可以将消息路由到一个或多个目的地。利用这个功能,我们就能完美的解决该问题,下面我们来说说Spring Cloud Bus中的具体实现方案。
在《Spring Boot中使用RabbitMQ》一文中,我们已经介绍了关于消息代理、AMQP协议以及RabbitMQ的基础知识和使用方法。下面我们开始具体介绍Spring Cloud Bus的配置,并以一个Spring Cloud Bus与Spring Cloud Config结合的例子来实现配置内容的实时更新。
RabbitMQ实现
下面我们来具体动手尝试整个配置过程:
- 准备工作:这里我们不做新的应用,但需要用到上一章中,我们已经实现的关于Spring Cloud Config的几个工程,若读者对其还不了解,建议先阅读第4章的内容。
- config-repo:定义在Git仓库中的一个目录,其中存储了应用名为didispace的多环境配置文件,配置文件中有一个from参数。
- config-server-eureka:配置了Git仓库,并注册到了Eureka的服务端。
- config-client-eureka:通过Eureka发现Config Server的客户端,应用名为didispace,用来访问配置服务器以获取配置信息。该应用中提供了一个
/from接口,它会获取config-repo/didispace-dev.properties中的from属性返回。
- 扩展config-client-eureka应用
- 修改
pom.xml增加spring-cloud-starter-bus-amqp模块(注意spring-boot-starter-actuator模块也是必须的)。
- 修改
|
1
2
3
4
|
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
|
- 在配置文件中增加关于RabbitMQ的连接和用户信息
|
1
2
3
4
|
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456
|
- 启动config-server-eureka,再启动两个config-client-eureka(分别在不同的端口上,比如7002、7003),我们可以在config-client-eureka中的控制台中看到如下内容,在启动时候,客户端程序多了一个
/bus/refresh请求。
|
1
|
o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/bus/refresh],methods=[POST]}" onto public void org.springframework.cloud.bus.endpoint.RefreshBusEndpoint.refresh(java.lang.String)
|
- 先访问两个config-client-eureka的
/from请求,会返回当前config-repo/didispace-dev.properties中的from属性。 - 接着,我们修改
config-repo/didispace-dev.properties中的from属性值,并发送POST请求到其中的一个/bus/refresh。 - 最后,我们再分别访问启动的两个config-client-eureka的
/from请求,此时这两个请求都会返回最新的config-repo/didispace-dev.properties中的from属性。
到这里,我们已经能够通过Spring Cloud Bus来实时更新总线上的属性配置了。
原理分析
我们通过使用Spring Cloud Bus与Spring Cloud Config的整合,并以RabbitMQ作为消息代理,实现了应用配置的动态更新。

整个方案的架构如上图所示,其中包含了Git仓库、Config Server、以及微服务“Service A”的三个实例,这三个实例中都引入了Spring Cloud Bus,所以他们都连接到了RabbitMQ的消息总线上。
当我们将系统启动起来之后,“Service A”的三个实例会请求Config Server以获取配置信息,Config Server根据应用配置的规则从Git仓库中获取配置信息并返回。
此时,若我们需要修改“Service A”的属性。首先,通过Git管理工具去仓库中修改对应的属性值,但是这个修改并不会触发“Service A”实例的属性更新。我们向“Service A”的实例3发送POST请求,访问/bus/refresh接口。此时,“Service A”的实例3就会将刷新请求发送到消息总线中,该消息事件会被“Service A”的实例1和实例2从总线中获取到,并重新从Config Server中获取他们的配置信息,从而实现配置信息的动态更新。
而从Git仓库中配置的修改到发起/bus/refresh的POST请求这一步可以通过Git仓库的Web Hook来自动触发。由于所有连接到消息总线上的应用都会接受到更新请求,所以在Web Hook中就不需要维护所有节点内容来进行更新,从而解决了通过Web Hook来逐个进行刷新的问题。
指定刷新范围
上面的例子中,我们通过向服务实例请求Spring Cloud Bus的/bus/refresh接口,从而触发总线上其他服务实例的/refresh。但是有些特殊场景下(比如:灰度发布),我们希望可以刷新微服务中某个具体实例的配置。
Spring Cloud Bus对这种场景也有很好的支持:/bus/refresh接口还提供了destination参数,用来定位具体要刷新的应用程序。比如,我们可以请求/bus/refresh?destination=customers:9000,此时总线上的各应用实例会根据destination属性的值来判断是否为自己的实例名,若符合才进行配置刷新,若不符合就忽略该消息。
destination参数除了可以定位具体的实例之外,还可以用来定位具体的服务。定位服务的原理是通过使用Spring的PathMatecher(路径匹配)来实现,比如:/bus/refresh?destination=customers:**,该请求会触发customers服务的所有实例进行刷新。
架构优化
既然Spring Cloud Bus的/bus/refresh接口提供了针对服务和实例进行配置更新的参数,那么我们的架构也相应的可以做出一些调整。在之前的架构中,服务的配置更新需要通过向具体服务中的某个实例发送请求,再触发对整个服务集群的配置更新。虽然能实现功能,但是这样的结果是,我们指定的应用实例就会不同于集群中的其他应用实例,这样会增加集群内部的复杂度,不利于将来的运维工作,比如:我们需要对服务实例进行迁移,那么我们不得不修改Web Hook中的配置等。所以我们要尽可能的让服务集群中的各个节点是对等的。
因此,我们将之前的架构做了一些调整,如下图所示:

我们主要做了这些改动:
- 在Config Server中也引入Spring Cloud Bus,将配置服务端也加入到消息总线中来。
/bus/refresh请求不在发送到具体服务实例上,而是发送给Config Server,并通过destination参数来指定需要更新配置的服务或实例。
通过上面的改动,我们的服务实例就不需要再承担触发配置更新的职责。同时,对于Git的触发等配置都只需要针对Config Server即可,从而简化了集群上的一些维护工作。
本文完整示例:
- 开源中国:http://git.oschina.net/didispace/SpringCloud-Learning/tree/master/Chapter1-1-7
- GitHub:https://github.com/dyc87112/SpringCloud-Learning/tree/master/Chapter1-1-7
Spring Cloud构建微服务架构(七)消息总线的更多相关文章
- Spring Cloud构建微服务架构
Dalston版本 由于Brixton和Camden版本的教程已经停止更新,所以笔者计划在2017年上半年完成Dalston版本的教程编写(原计划完成Camden版本教程,但由于写了两篇Dalston ...
- Spring Cloud构建微服务架构(三)消息总线
注:此文不适合0基础学习者直接阅读,请先完整的将作者关于微服务的博文全部阅读一遍,如果还有疑问,可以再来阅读此文,地址:http://blog.csdn.net/sosfnima/article/d ...
- 《Spring Cloud构建微服务架构》系列博文示例
SpringCloud-Learning 源码下载地址:http://download.csdn.net/detail/k21325/9650968 本项目内容为Spring Cloud教 ...
- Spring Cloud构建微服务架构(二)服务消费者
Netflix Ribbon is an Inter Process Communication (IPC) cloud library. Ribbon primarily provides clie ...
- Spring Cloud构建微服务架构:服务网关(路由配置)【Dalston版】
转载:http://blog.didispace.com/spring-cloud-starter-dalston-6-2/ 原创 2017-08-26 翟永超 Spring Cloud 被围观 ...
- Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台
Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud
- Spring Cloud构建微服务架构(五)服务网关
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...
- Spring Cloud构建微服务架构 - 服务网关
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...
- Spring Cloud构建微服务架构(一)服务注册与发现
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...
- 第1章 Spring Cloud 构建微服务架构(一)服务注册与发现
一.Spring Cloud 简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总 ...
随机推荐
- IOS语言总结
本文主要介绍和C++不同的地方. 1.类的定义: 一个类有两个文件一个.h还有一个.m文件 #import <Foundation/Foundation.h> @interface MyC ...
- foreach的使用原理简单解析
数组可以foreach遍历,这个是在jdk1.5之前就可以的,我也不太清楚是怎么做到的. 后面的List,Set等的foreach都是实现Iterable接口,基于iterator()对象实现的.Fo ...
- oracle主从表主外键对应关系
一.首先让我们来了解下什么是主外键? 1.主键:唯一标识数据表中的某一行 1) 一个表中只能有一个主键.如果在其他字段上建立主键,则原来的主键就会取消.在ACCESS中,虽然主键不是必需的,但最好为每 ...
- 06-python opencv 使用摄像头捕获视频并显示
https://blog.csdn.net/huanglu_thu13/article/details/52337013
- X-Mirage苹果屏幕录制工具7天试用期破解 imsoft.cnblogs
X-Mirage (PC) 能让你的 Windows 变成一个 iPhone.iPad 或者 iPod Touch 的屏幕镜像,应用程序.游戏.照片.视频等等一切可以在 iOS 移动端显示的东西,都镜 ...
- HDU1070:Milk
Milk Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- C#/.NET 使用 CommandLineParser 来标准化地解析命令行
CommandLineParser 是一款用于解析命令行参数的 NuGet 包.你只需要关注你的业务,而命令行解析只需要极少量的配置代码. 本文将介绍如何使用 CommandLineParser 高效 ...
- koa-connect源码解析
文中提到的koa均为koa2 提到nodejs, 想必大家都知道express和koa. express: 大 koa: 小 比较的的是功能, 社区, 中间件,相关资源等 这里我就专门说说中间件吧, ...
- map和jsonObject 这2中数据结构之间转换
前台写json直接是:var array = [ ] ; 调用方法:array[index],若是对象,再[“key”] var obj = {''a'':123 , "b":&q ...
- ubuntu14.04下安装ffmpeg
ubuntu14.04下安装ffmpeg 一.安装各种依赖包 1.yasm(libx264需要依赖yasm) sudo apt-get install yasm 2.libx264 sudo apt- ...