Spring Cloud Stream 核心概念
Spring Cloud Stream简介
Spring cloud stream是一个构建与Spring Boot和Spring Integration之上的框架,方便开发人员快速构建基于Message-Driven的系统。
Spring Integration & Enterprise Integration Patterns简介
Enterprise Integration Patterns 是由Gregor Hohpe和Bobby Woolf在 Enterprise Integration Patterns 一书中总结的企业应用开发实践中使用到的各系统间数据交换的方式。
Spring Integration是Spring框架对Enterprise Integration Patterns的实现和适配。Spring Integration在基于Spring的应用程序中实现轻量级消息传递,并支持通过声明适配器与外部系统集成。 与Spring对远程处理,消息传递和调度的支持相比,这些适配器提供了更高级别的抽象。 Spring Integration的主要目标是提供一个简单的模型来构建企业集成解决方案,同时保持关注点的分离,这对于生成可维护的可测试代码至关重要。
常见的企业集成数据传递模式有以下几种:
- 文件传输:系统A采用FTP轮询等方式获取系统B生成的文件等。
- 共享数据库:系统A和系统B共用一个数据库表,共用实体类。
- RPC调用:系统A和B暴露互相之间能调用的服务,例如SOAP、REST。
- 消息传递:系统A和系统B通过消息中间价交换数据。
Spring Cloud Stream 优点
- 和MQ中间件解耦:相较同样是针对MQ中间价集成的Spring Message项目,提供了更高层的面向不同MQ中间件代理(RabbitMQ、Kafka等)的Binder抽象,为开发人员提供了统一的编程模型。例如RabbitMQ原生并不支持partition特性,如果想要从Kafaka迁移到RabbitMQ,就需要修改一堆代码,但是如果是Spring Cloud Stream则有可能只需要修改几个配置即可。
- 错误重试:集成Spring Retry提供了错误自动重试功能。
- Error Handler:提供application和system两层的异常处理机制。
Spring Cloud Stream核心概念
Spring Cloud Stream官网的核心架构图
Binder 层负责和MQ中间件的通信,应用程序 Application Core 通过 inputs 接收 Binder 包装后的 Message,相当于是消费者Consumer;通过 outputs 投递 Message给 Binder,然后由 Binder 转换后投递给MQ中间件,相当于是生产者Producer。
Channel
Channel
描述的是消息从应用程序和Binder
之间的流通的通道,也就是Application Model
中的input
和output
。
Binder
Binder
是Spring Cloud Stream中一个非常重要的概念,它是应用程序和消息中间件的中间层,完美屏蔽了不同消息中间件的实现差异,可以简单的类比为Adapter
。
Spring Cloud Stream官方提供了spring-cloud-stream-binder-kafka
和spring-cloud-stream-binder-rabbit
两款主流消息中间件的Binder
实现。并且还提供了专门用于测试的TestSupportBinder
,开发者可以直接使用它来对通道的接收内容进行断言测试。
当然,Spring Cloud Stream也允许开发者通过它的SPI来实现其他MQ的Binder
。目前已有多款MQ产品提供了第三方Binder
实现,参考官方文档Binder Implementions。如要实现自己的Binder
可以参考官方文档Binder SPI。
Bindings
Binding
是用于描述MQ中间件到应用程序的桥梁模型,即是对于Binder
加上inputs
和outputs
各个channel
的绑定关系的描述。例如:RabbitMQ-Binder
+ channel-input1
。
Spring Cloud Stream通过spring.cloud.stream.bindings.<channelName>
来确定绑定关系。
Spring Cloud Stream已经包含了以下几个Bindings
接口:
Source
-定义了应用程序作为生产者将消息投递到一个名为output
的channel
中去。
public interface Source {
/**
* Name of the output channel.
*/
String OUTPUT = "output";
/**
* @return output channel
*/
@Output(Source.OUTPUT)
MessageChannel output();
}
Sink
-定义了应用程序作为消费者消费名为input
的channel
中的消息。
public interface Sink {
/**
* Input channel name.
*/
String INPUT = "input";
/**
* @return input channel.
*/
@Input(Sink.INPUT)
SubscribableChannel input();
}
Processor
-定义了应用程序同时作为生产者和消费者,生产消息到名为output
的通道,消费来自名为input
通道的消息。
public interface Processor extends Source, Sink {
}
当然,这几个预定义的接口必然无法满足复杂的业务逻辑,因此Spring Cloud Stream也支持开发人员自定义Bindings
接口。
Pub-sub
spring cloud stream支持的是共享topics
的publish-subscribe
模型,并没有采用point-to-point
的queues
模型,因为pub-sub模型在微服务中更具有普适性。而且pub-sub模型也能通过只有一个消费者来变相支持p2p模型。
kafka是最典型的pub-sub主流MQ中间件,spring cloud stream在术语和特性支持上基本和kafka类似。
Consumer group
在普通的pub-sub关系中,多个consumer
在订阅了同一个topic
时,这些consumer
之间是竞争关系,即topic
中的一条消息只会被其中一个consumer
消费。但如果这些consumer
不属于同一个服务怎么办,例如下单topic
的下游会有库存服务、账户服务等多个服务的消费者同时存在,这些不同服务的消费者都需要获取到下单topic
中的消息,否则就无法触发相应的操作,难道需要给不同服务排个队依次传递消息,那就变成了同步操作了。
在kafka中通过Consumer Group
消费者分组来处理上述问题。一个topic
中的每一条消息都会采取多副本的方式分发给所有订阅的Consumer Group
,每个Consumer Group
中的Consumer
之间则竞争消费。即库存服务和账户服务的消费组属于不同的Consumer Group
,两个服务都会得到下单topic
的消息,但是同一个服务只会有一个Consumer
实例会实际消费。
Spring Clous Stream也支持了kafka的这一特性,每个Consumer
可以通过spring.cloud.stream.bindings.<channelName>.group
属性设置自己所属的Consumer Group
。
默认情况下,如果我们没有为Consumer
指定消费组的话,Spring Cloud Stream会为其分配一个独立的匿名消费组。所以如果某topic
下的所有consumers
都未指定消费组时,当有消息发布后,所有的consumers
都会对其进行消费,因为它们各自属于独立的组。因此,我们建议在使用Spring Cloud Stream时最好都指定Consumer Group
,以防止对消息的重复消费,除非该行为是必要的(例如刷新所有consumer
的配置等)。
Polled Consumer
spring cloud stream 2.0之后开始支持定时拉取的消费模式,开发人员可以指定拉取频率以及最大拉取消息数量来控制消费速率。
Partition
通过Consumer Group
我们已经能保障每条消息只会被组内的某个实例消费一次,但是我们无法控制消息会被哪一个实例消费。即多条消息到达后,它们可能是分别由不同的consumer
实例消费。
但是对于一些业务场景,就需要针对某些具有相同特征的消息每次都可以被同一个消费者实例消费,例如某些监控计数服务,需要针对相同uid的行为在内存中计数。因此,MQ中间件引入了消息分区的概念,消息根据特征写入到不同的partition,不同的消费者实例指定消费不同分区的消息,于是保证相同特征的消息会被同一个消费者实例消费。
Spring Cloud Stream针对patition提供了一个通用的抽象,用来在消息中间件的上层实现分区处理,所以它对于消息中间件自身是否实现了消息分区并不关心,这使得Spring Cloud Stream为不具备分区功能的消息中间件也增加了分区功能扩展(例如RabbitMQ)。
Spring Cloud Stream 核心概念的更多相关文章
- Spring Cloud Stream教程(二)主要概念
Spring Cloud Stream提供了一些简化了消息驱动的微服务应用程序编写的抽象和原语.本节概述了以下内容: Spring Cloud Stream的应用模型 Binder抽象 持续的发布 - ...
- Spring Cloud Stream如何消费自己生产的消息?
在上一篇<Spring Cloud Stream如何处理消息重复消费>中,我们通过消费组的配置解决了多实例部署情况下消息重复消费这一入门时的常见问题.本文将继续说说在另外一个被经常问到的问 ...
- 第十章 消息驱动的微服务: Spring Cloud Stream
Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架. 它可以基于Spring Boot 来创建独立的. 可用于生产的 Spring 应用程序. 它通过使用 Sprin ...
- Spring Cloud Stream(十三)
说明 对Spring Boot 和 Spring Integration的整合,通过Spring Cloud Stream能够简化消息中间件使用的复杂难度!让业务人员更多的精力能够花在业务层面 简单例 ...
- Spring cloud stream【入门介绍】
案例代码:https://github.com/q279583842q/springcloud-e-book 在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,而以往使用了哪个中间件比如 ...
- 消息驱动式微服务:Spring Cloud Stream & RabbitMQ
1. 概述 在本文中,我们将向您介绍Spring Cloud Stream,这是一个用于构建消息驱动的微服务应用程序的框架,这些应用程序由一个常见的消息传递代理(如RabbitMQ.Apache Ka ...
- Spring Cloud 系列之 Spring Cloud Stream
Spring Cloud Stream 是消息中间件组件,它集成了 kafka 和 rabbitmq .本篇文章以 Rabbit MQ 为消息中间件系统为基础,介绍 Spring Cloud Stre ...
- SpringCloud之Spring Cloud Stream:消息驱动
Spring Cloud Stream 是一个构建消息驱动微服务的框架,该框架在Spring Boot的基础上整合了Spring Integrationg来连接消息代理中间件(RabbitMQ, Ka ...
- spring cloud 2.x版本 Spring Cloud Stream消息驱动组件基础教程(kafaka篇)
本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka-ri ...
随机推荐
- HDU5521 Meeting(dijkstra+巧妙建图)
HDU5521 Meeting 题意: 给你n个点,它们组成了m个团,第i个团内有si个点,且每个团内的点互相之间距离为ti,问如果同时从点1和点n出发,最短耗时多少相遇 很明显题目给出的是个无负环的 ...
- SSAS Tabular 表格模型建模(关系)及部署
一.表格建模(SSAS 表格) 表格模型是 Analysis Services 中的内存中数据库. 使用最先进的压缩算法和多线程查询处理器,xVelocity 内存中分析引擎 (VertiPaq) ...
- Asp.Net Core SwaggerUI 接入
Asp.Net Core SwaggerUI 接入 简单了解 swagger的目的简单来说就是,不用为每个接口手动写接口文档,因为它是根据接口自动生成的,接口更改时文档也同步更新,减少了手动更新的麻烦 ...
- SpringBoot学习笔记2
九:创建父工程 注意:打包方式选择为pom 将创建SpringBoot常用的依赖和插件放在父工程的pom.xml,如下: <project xmlns="http://maven.ap ...
- C语言入门7-程序设计方法基础-循环结构
程序设计方法基础-循环结构 循环三要素: 初值 循环判断条件 步长(循环增量) 循环结构在有些书籍上也称为重复结构, 即反复执行某一部分的操作. 循环三要素: 初值 循环判断条件 步 ...
- md文件的书写《一》
标题 :标题大小取决于#的多少 嵌套标题 使用 * - + 中的任一个加空格就可以实现创建列表 多层嵌套 我见青山多妩媚 (右边的尖括号加内容,实现引用) 这是第一段文字. 这是第二段文字. 段落以回 ...
- Java学习笔记之---Servlet
Java学习笔记之---Servlet (一)如何实现Servlet 1.实现javax.servlet.Servlet接口: 2.继承javax.servlet.GenericServlet类: 3 ...
- c++ 动态规划(数塔)
c++ 动态规划(dp) 题目描述 观察下面的数塔.写一个程序查找从最高点到底部任意位置结束的路径,使路径经过数字的和最大. 每一步可以从当前点走到左下角的点,也可以到达右下角的点. 输入 5 13 ...
- python函数闭包-装饰器-03
可调用对象 callable() # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即 callable(对象) 返回为 True 的对象 x = 1 print(cal ...
- VMware里装XP 没有找到硬盘驱动器
遇到问题: 解决:要给虚拟机配上一个虚拟的硬盘驱动器.在VMWare的虚拟机配置里面给这个虚拟机增加硬盘,选IDE模式,而非SCSI,设定硬盘大小和文件名就可以了.