消息驱动的微服务器,Spring Cloud架构教程 (七)消息驱动的微服务(核心概念)【Dalston版】...

下图是官方文档中对于Spring Cloud Stream应用模型的结构图。从中咱们能够看到,Spring Cloud Stream构建的应用程序与消息中间件之间是经过绑定器Binder相关联的,绑定器对于应用程序而言起到了隔离做用,它使得不一样消息中间件的实现细节对应用程序来讲是透明的。因此对于每个Spring Cloud Stream的应用程序来讲,它不须要知晓消息中间件的通讯细节,它只须要知道Binder对应用程序提供的概念去实现便可,而这个概念就是在快速入门中咱们提到的消息通道:Channel。以下图案例,在应用程序和Binder之间定义了两条输入通道和三条输出通道来传递消息,而绑定器则是做为这些通道和消息中间件之间的桥梁进行通讯。html

c36c907b5ff3ebbc7ffc22e042aeef56.png

绑定器

Binder绑定器是Spring Cloud Stream中一个很是重要的概念。在没有绑定器这个概念的状况下,咱们的Spring Boot应用要直接与消息中间件进行信息交互的时候,因为各消息中间件构建的初衷不一样,它们的实现细节上会有较大的差别性,这使得咱们实现的消息交互逻辑就会很是笨重,由于对具体的中间件实现细节有过重的依赖,当中间件有较大的变更升级、或是更换中间件的时候,咱们就须要付出很是大的代价来实施。spring

经过定义绑定器做为中间层,完美地实现了应用程序与消息中间件细节之间的隔离。经过向应用程序暴露统一的Channel通道,使得应用程序不须要再考虑各类不一样的消息中间件实现。当咱们须要升级消息中间件,或是更换其余消息中间件产品时,咱们要作的就是更换它们对应的Binder绑定器而不须要修改任何Spring Boot的应用逻辑。这一点在上一章实现消息总线时,从RabbitMQ切换到Kafka的过程当中,已经可以让咱们体验到这一好处。架构

目前版本的Spring Cloud Stream为主流的消息中间件产品RabbitMQ和Kafka提供了默认的Binder实现,在快速入门的例子中,咱们就使用了RabbitMQ的Binder。另外,Spring Cloud Stream还实现了一个专门用于测试的TestSupportBinder,开发者能够直接使用它来对通道的接收内容进行可靠的测试断言。若是要使用除了RabbitMQ和Kafka之外的消息中间件的话,咱们也能够经过使用它所提供的扩展API来实现其余中间件的Binder。app

仔细的读者可能已经发现,咱们在快速入门示例中,并无使用application.properties或是application.yml来作任何属性设置。那是由于它也秉承了Spring Boot的设计理念,提供了对RabbitMQ默认的自动化配置。固然,咱们也能够经过Spring Boot应用支持的任何方式来修改这些配置,好比:经过应用程序参数、环境变量、application.properties或是application.yml配置文件等。好比,下面就是经过配置文件来对RabbitMQ的链接信息以及input通道的主题进行配置的示例:负载均衡

spring.cloud.stream.bindings.input.destination=raw-sensor-data

spring.rabbitmq.host=localhost

spring.rabbitmq.port=5672

spring.rabbitmq.username=springcloud

spring.rabbitmq.password=123456

发布-订阅模式

在Spring Cloud Stream中的消息通讯方式遵循了发布-订阅模式,当一条消息被投递到消息中间件以后,它会经过共享的Topic主题进行广播,消息消费者在订阅的主题中收到它并触发自身的业务逻辑处理。这里所提到的Topic主题是Spring Cloud Stream中的一个抽象概念,用来表明发布共享消息给消费者的地方。在不一样的消息中间件中,Topic可能对应着不一样的概念,好比:在RabbitMQ中的它对应了Exchange、而在Kakfa中则对应了Kafka中的Topic。微服务

在快速入门的示例中,咱们经过RabbitMQ的Channel进行发布消息给咱们编写的应用程序消费,而实际上Spring Cloud Stream应用启动的时候,在RabbitMQ的Exchange中也建立了一个名为input的Exchange交换器,因为Binder的隔离做用,应用程序并没有法感知它的存在,应用程序只知道本身指向Binder的输入或是输出通道。为了直观的感觉发布-订阅模式中,消息是如何被分发到多个订阅者的,咱们可使用快速入门的例子,经过命令行的方式启动两个不一样端口的进程。此时,咱们在RabbitMQ控制页面的Channels标签页中看到以下图所示的两个消息通道,它们分别绑定了启动的两个应用程序。测试

f464e0ea16e9918ed4408dbd723c151e.png

而在Exchanges标签页中,咱们还能找到名为input的交换器,点击进入能够看到以下图所示的详情页面,其中在Bindings中的内容就是两个应用程序绑定通道中的消息队列,咱们能够经过Exchange页面的Publish Message来发布消息,此时能够发现两个启动的应用程序都输出了消息内容。spa

39e505d14680a9174972bf6f6b51cd3c.png

下图总结了咱们上面所作尝试的基础结构,咱们启动的两个应用程序分别是“订阅者-1”和“订阅者-2”,他们都创建了一条输入通道绑定到同一个Topic(RabbitMQ的Exchange)上。当该Topic中有消息发布进来后,链接到该Topic上的全部订阅者能够收到该消息并根据自身的需求进行消费操做。命令行

b00ab078b386cd053f359a9afbfd3e72.png

相对于点对点队列实现的消息通讯来讲,Spring Cloud Stream采用的发布-订阅模式能够有效的下降消息生产者与消费者之间的耦合,当咱们须要对同一类消息增长一种处理方式时,只须要增长一个应用程序并将输入通道绑定到既有的Topic中就能够实现功能的扩展,而不须要改变原来已经实现的任何内容。设计

消费组

虽然Spring Cloud Stream经过发布-订阅模式将消息生产者与消费者作了很好的解耦,基于相同主题的消费者能够轻松的进行扩展,可是这些扩展都是针对不一样的应用实例而言的,在现实的微服务架构中,咱们每个微服务应用为了实现高可用和负载均衡,实际上都会部署多个实例。不少状况下,消息生产者发送消息给某个具体微服务时,只但愿被消费一次,按照上面咱们启动两个应用的例子,虽然它们同属一个应用,可是这个消息出现了被重复消费两次的状况。为了解决这个问题,在Spring Cloud Stream中提供了消费组的概念。

若是在同一个主题上的应用须要启动多个实例的时候,咱们能够经过spring.cloud.stream.bindings.input.group属性为应用指定一个组名,这样这个应用的多个实例在接收到消息的时候,只会有一个成员真正的收到消息并进行处理。以下图所示,咱们为Service-A和Service-B分别启动了两个实例,而且根据服务名进行了分组,这样当消息进入主题以后,Group-A和Group-B都会收到消息的副本,可是在两个组中都只会有一个实例对其进行消费。

c3607f9096bcba5117b72cec8a47facb.png

默认状况下,当咱们没有为应用指定消费组的时候,Spring Cloud Stream会为其分配一个独立的匿名消费组。因此,若是同一主题下全部的应用都没有指定消费组的时候,当有消息被发布以后,全部的应用都会对其进行消费,由于它们各自都属于一个独立的组中。大部分状况下,咱们在建立Spring Cloud Stream应用的时候,建议最好为其指定一个消费组,以防止对消息的重复处理,除非该行为须要这样作(好比:刷新全部实例的配置等)。

09bb922e076098a8933f3e24b7a69a4e.png

消息分区

经过引入消费组的概念,咱们已经可以在多实例的状况下,保障每一个消息只被组内一个实例进行消费。经过上面对消费组参数设置后的实验,咱们能够观察到,消费组并没有法控制消息具体被哪一个实例消费。也就是说,对于同一条消息,它屡次到达以后多是由不一样的实例进行消费的。可是对于一些业务场景,就须要对于一些具备相同特征的消息每次均可以被同一个消费实例处理,好比:一些用于监控服务,为了统计某段时间内消息生产者发送的报告内容,监控服务须要在自身内容聚合这些数据,那么消息生产者能够为消息增长一个固有的特征ID来进行分区,使得拥有这些ID的消息每次都能被发送到一个特定的实例上实现累计统计的效果,不然这些数据就会分散到各个不一样的节点致使监控结果不一致的状况。而分区概念的引入就是为了解决这样的问题:当生产者将消息数据发送给多个消费者实例时,保证拥有共同特征的消息数据始终是由同一个消费者实例接收和处理。

Spring Cloud Stream为分区提供了通用的抽象实现,用来在消息中间件的上层实现分区处理,因此它对于消息中间件自身是否实现了消息分区并不关心,这使得Spring Cloud Stream为不具有分区功能的消息中间件也增长了分区功能扩展。源码来源

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值