SpringCloud Stream消息驱动

2023-10-30

一、SpringCloud Stream概述

RabbitMQ和Kafka这两个消息中间件的架构上是不同的:
RabbitMQ有exchange,kafka有Topic,partitions分区。
这些中间件的差异性导致,当业务需求要往另外一种消息队列迁移时,因为两者跟系统耦合,一大堆东西要重新做。但springcloud Stream提供了一种解耦合的方式。

Spring Cloud Stream 是一个构建消息驱动微服务的框架。Spring Cloud Stream 的 binder 负责与中间件(kafka、MQ)交互。应用程序通过 input (消费者consumer,从队列中接收消息)或者 output(生产者producer,给队列中发送消息) 来与 Spring Cloud Stream 中binder 交互,通过配置来 binding。
在这里插入图片描述

二、Binder

Binder 是 Spring Cloud Stream 的一个抽象概念,是应用与消息中间件之间的粘合剂。Spring Cloud Stream 实现了 Kafka 和 Rabbit MQ 的binder。通过 binder连接中间件,可以动态的改变消息的destinations(对应于Kafka 的topic,RabbitMQ 的 exchanges),这些都可以通过外部配置项来做到。甚至可以任意的改变中间件的类型而不需要修改一行代码。

三、Consumer Groups【针对消费者】

“Group”:在Spring Cloud Stream 中“分组”概念的含义基本和 Kafka 一致。把应用放置于同一个 “group” 中 【ps:kafka中group类比于MQ中的队列,故而,Kafka中消费者在同一个group就类比于MQ的消费者们用同一个队列】 ,可防止同一个事件被重复消费,保证消息被其中一个应用消费一次后别的应用消费不到。

四、Publish-Subscribe

Spring Cloud Stream 生产者把消息通过某个 topic (就是destinations)广播出去。消费者通过订阅特定 topic 来获取广播出来的消息。

介绍一下yml配置的含义:

看配置文件中注解的解释:
在这里插入图片描述

@EnableBinding(Source.class)可以绑定多个,数组形式{    }
这个@EnableBinding是绑定消息通道的,Source是Stream提供的,可以点进去看源码,有output和input,这和配置文件中的output,input对应的。

yml配置文件中切记bingdings.output,yml配置文件中的output就是@output(value=" ")注解的value值,是绝对的对应,
只不过默认是input【输入管道】、output【输出管道】。

@StreamListener(管道id,如Sink.INPUT),
@input(value = " ")管道id就是@input注解里的value的值。


五、消息分组

生产环境一个服务启动多个实例时,这些实例都被绑到同一个消息通道的目标主题(Kafka中是topic、mq中是exchange,在springcloud stream中就是destination)。会出现一个生产者发一条消息,消息通过@output通道,从destination中发出,这个destination又被多个@input消费者通道监听,导致每个监听同一个destination的消费者们都能接受处理消息。

(ps:以MQ说明,本质上,就是每个消费者实例,被分配到了分别不同的queue,交换机广播到每个队列,多实例都可获取同样的消息)

但是在业务需求下,要求被其中一个消费者消费,而不是被所有消费者消费。

上案例:【仅在消费者方配置即可】
消费者1:
在这里插入图片描述
消费者2:
在这里插入图片描述

如此一来,配置了消费者1和消费者2在同一个分组(ps:类比MQ,将两个消费者实例绑定同一个队列上,队列里的信息只能被其中一个消费)

达到目的:
生产者模块发的消息只能被消费者1或消费者2其中一个接收到,避免了重复消费。

六、消息分区

一个/多个生产者应用实例给多个消费者应用实例发送消息,确保相同特征的数据被同一消费者实例处理。

Spring Cloud Stream对partitions实现进行了抽象。使得不具备分区功能的消息中间件(RabbitMQ)也增加了分区功能扩展。

(1)生产者方配置:

spring:
  application:
    name: producer
  cloud:
    stream:
      kafka:
        binder:
          brokers: localhost:9092
          zk-nodes: localhost:2181
          auto-create-topics: true
      bindings:
        myOutput:
            destination: stream-demo
            content-type: text/plain
            producer:
              partitionKeyExpression: payload  #分区的主键(key),【这里payload是一个对象的id用做为Key】
              partitionCount: 2    #这里分区数量配置为2【Key和分区数量进行取模去分配消息】
  1. Spring.cloud.stream.bindings.output.producer.partitionKeyExpression :通过该参数指定了分区键的表达式规则,我们可以根据实际的输出消息规则来配置SpEL来生成合适的分区键;
  2. spring.cloud.stream.bindings.output.producer.partitionCount :该参数指定了消息分区的数量。

(2)消费者方配置:

生产者配了2个分区,

消费者1、消费者2配置消费者总数为2,并设置自己的索引,这里分别是0、1
在这里插入图片描述

在这里插入图片描述
再次启动多个生产者实例应用,并且启动多个消费者(ps:在消费者配置文件里一定要为消费者指定不同的索引号),这样当同一个消息被发给消费者们时,只有一个消费实例在接收和处理同一批(注:这一批是一个整体)的消息。

解释:
(1)因为生产者分区的Key是一个生产者实例对象的id,比如说id=1,如果每次生产者对象的id为1,则消息只会被索引为1的同一个消费者消费;

(2)分区数量取模的作用—>
生产者实例的Key值和分区数量取模计算的结果是1,分到消费者2【配置文件中索引为1】模块中,那么下一次进行消息发送,只要分组的key(即id的值)依然是1的话,消息永远只会分配到消费者2模块中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringCloud Stream消息驱动 的相关文章

随机推荐