Spring Cloud Stream 核心概念

Spring Cloud Stream简介

Spring cloud stream是一个构建与Spring Boot和Spring Integration之上的框架,方便开发人员快速构建基于Message-Driven的系统。html

Spring Integration & Enterprise Integration Patterns简介

Enterprise Integration Patterns 是由Gregor Hohpe和Bobby Woolf在 Enterprise Integration Patterns 一书中总结的企业应用开发实践中使用到的各系统间数据交换的方式。java

Spring Integration是Spring框架对Enterprise Integration Patterns的实现和适配。Spring Integration在基于Spring的应用程序中实现轻量级消息传递,并支持经过声明适配器与外部系统集成。 与Spring对远程处理,消息传递和调度的支持相比,这些适配器提供了更高级别的抽象。 Spring Integration的主要目标是提供一个简单的模型来构建企业集成解决方案,同时保持关注点的分离,这对于生成可维护的可测试代码相当重要。spring

常见的企业集成数据传递模式有如下几种:数据库

  • 文件传输:系统A采用FTP轮询等方式获取系统B生成的文件等。
  • 共享数据库:系统A和系统B共用一个数据库表,共用实体类。
  • RPC调用:系统A和B暴露互相之间能调用的服务,例如SOAP、REST。
  • 消息传递:系统A和系统B经过消息中间价交换数据。

Spring Cloud Stream 优势

  1. 和MQ中间件解耦:相较一样是针对MQ中间价集成的Spring Message项目,提供了更高层的面向不一样MQ中间件代理(RabbitMQ、Kafka等)的Binder抽象,为开发人员提供了统一的编程模型。例如RabbitMQ原生并不支持partition特性,若是想要从Kafaka迁移到RabbitMQ,就须要修改一堆代码,可是若是是Spring Cloud Stream则有可能只须要修改几个配置便可。
  2. 错误重试:集成Spring Retry提供了错误自动重试功能。
  3. Error Handler:提供application和system两层的异常处理机制。

Spring Cloud Stream核心概念

spring-cloud-stream-application

Spring Cloud Stream官网的核心架构图编程

Binder 层负责和MQ中间件的通讯,应用程序 Application Core 经过 inputs 接收 Binder 包装后的 Message,至关因而消费者Consumer;经过 outputs 投递 Message给 Binder,而后由 Binder 转换后投递给MQ中间件,至关因而生产者Producer。api

Channel

Channel描述的是消息从应用程序和Binder之间的流通的通道,也就是Application Model中的inputoutput架构

Binder

Binder是Spring Cloud Stream中一个很是重要的概念,它是应用程序和消息中间件的中间层,完美屏蔽了不一样消息中间件的实现差别,能够简单的类比为Adapterapp

Spring Cloud Stream官方提供了spring-cloud-stream-binder-kafkaspring-cloud-stream-binder-rabbit两款主流消息中间件的Binder实现。而且还提供了专门用于测试的TestSupportBinder,开发者能够直接使用它来对通道的接收内容进行断言测试。框架

固然,Spring Cloud Stream也容许开发者经过它的SPI来实现其余MQ的Binder。目前已有多款MQ产品提供了第三方Binder实现,参考官方文档Binder Implementions。如要实现本身的Binder能够参考官方文档Binder SPI微服务

Bindings

Binding是用于描述MQ中间件到应用程序的桥梁模型,便是对于Binder加上inputsoutputs各个channel的绑定关系的描述。例如:RabbitMQ-Binder + channel-input1

Spring Cloud Stream经过spring.cloud.stream.bindings.<channelName>来肯定绑定关系。

Spring Cloud Stream已经包含了如下几个Bindings接口:

  • Source-定义了应用程序做为生产者将消息投递到一个名为outputchannel中去。
public interface Source {

        /**
         * Name of the output channel.
         */
        String OUTPUT = "output";
    
        /**
         * @return output channel
         */
        @Output(Source.OUTPUT)
        MessageChannel output();
    }
  • Sink-定义了应用程序做为消费者消费名为inputchannel中的消息。
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支持的是共享topicspublish-subscribe模型,并无采用point-to-pointqueues模型,由于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)。

相关文章
相关标签/搜索