Spring Cloud Stream (2)-原理篇

Spring Cloud Stream将消息投递和消费定义成3个概念,本文主要了解下这3个概念如何实现的,与不同的MQ是如何结合的。

 

发布-订阅模式:

当一条消息被投递到消息中间件之后,所有订阅次消息的Consumer都可以消费到这条消息。

RabbitMQ里是通过TopicExchange来实现的。

Kafka里是通过Toopic会被每个ConsumerGroup消费一次这个特性决定的。


消费组:

在微服务架构中,每个服务节点为了实现高可用和负载均衡实际上都会部署多个实例,如果只有发布-订阅模式就会导致同一个功能的服务节点会重复消费。为了解决这个问题,Spring Cloud Stream中提供了消费组的概念。

通过spring.cloud.stream.bindings.input.group属性为应用指定一个组名,MQ中的一条消息只能被同一个组名中的一个实例消费。(每个微服务结点启动后会默认获得一个独立的spring.cloud.stream.bindings.input.group,也就是自己一个组)。

RabbitMQ里每个QueueConsumer竞争消费的,所以指定同一个组的Consuemr消费同一个Queue就可以实现。

Kafka里自带Consumer Group的概念,,完美匹配消费组。


消息分区

         假如我想让相同的消息都被同一个微服务结点来处理,但是我有4个服务节点组成负载均衡,通过上述的消费组的概念仍不能满足我的要求,所以Spring Cloud Stream又为了此类场景引入消息分区的概念。当生产者将消息数据发送给多个消费者实例时,保证同一消息数据始终是由同一个消费者实例接收和处理。

Consumer端增加配置:

Spring.cloud.stream.bindings.input.consumer.partitioned=true

Spring.cloud.stream.instanceCount=2

Spring.cloud.stream.instanceIndex=0

Consumer的这3个配置理解起来相对简单,第一行开启消息分区,默认为false;第二行指定多少个分区;第三行指定当前服务节点是分区号。

Producer端增加配置:

Spring.cloud.stream.bindings.output.producer.partitionCount=2

Spring.cloud.stream.bindings.output.producer.partitionKeyExpression=payload

第一行对应Consumer里的配置,分多少个区;第二行是指定分区的算法,类似于hash算法,保证将同一消息hash到一个目的结点上。

 

 

一般发布-订阅模式独立使用,应用在Spring cloud config更新等广播类的场景,消息分组可以独立使用,也可以与消息分区搭配使用。