Spring Cloud Stream 消费组和分区

Spring Cloud Stream 消费组

通常每个服务都不会以单节点的方式运行在生产环境中,当同一个服务启动多个实例的时候,这些实例会绑定到同一个消息通道的目标主题上。默认情况下,当生产者发出一条消息到绑定通道上,这条消息会产生多个副本被每个消费者实例接收和处理。但是在有些业务场景之下,我们希望生产者产生的消息只被其中一个实例消费,这个时候就需要为这些消费者设置消费组来实现这样的功能。实现的方式非常简单,只需在服务消费者端设置spring.cloud.stream.bindings.input.group属性即可。

代码:

@EnableBinding({Sink.class,SinkSender.class})
public class SinkReceiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(SinkReceiver.class);

    @StreamListener(Sink.INPUT)
    public void receive(Object payload) {
        LOGGER.info("Received: {}", payload);
    }
}

配置:

spring:
 rabbitmq:
    host: 192.168.99.100
    port: 5672
    username: guest
    password: guest
 cloud:
   stream:
     bindings:
       input:
         group: service-a

然后我们同时启动两个App,之后我们在RabbitMQ的控制台上去发送消息。

在这里插入图片描述

发送两次message,然后我们可以看到message落在了两个不同的instance上。每个生产者发出的消息会被启动的消费者以轮询的方式进行接收和输出。

在这里插入图片描述

在这里插入图片描述

源代码参考:https://gitee.com/cckevincyh/cloud-stream-demo/tree/demo9/

Spring Cloud Stream 消息分区

通过消费组的设置,虽然我们已经能够在多实例环境下,保证同一消息只被一个消费者实例进行接收和处理,但是,对于一些特殊场景,除了要保证单一实例消费之外,还希望那些具备相同特征的消息都能够被同一个实例进行消费。这时候我们就需要对消息进行分区处理。

消费者的代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;

@EnableBinding({Sink.class})
public class SinkReceiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(SinkReceiver.class);

    @StreamListener(Sink.INPUT)
    public void receive(Object payload) {
        LOGGER.info("Received: {}", payload);
    }
}

消费者-1的配置:

spring:
 rabbitmq:
    host: 192.168.99.100
    port: 5672
    username: guest
    password: guest
 cloud:
   stream:
     instance-count: 2 # 消费者总数
     instance-index: 0 # 当前消费者的索引
     bindings:
       input:
         destination: greetings
         group: service-a
         consumer:
           partitioned: true # 开启分区支持

消费者-2的配置

spring:
 rabbitmq:
    host: 192.168.99.100
    port: 5672
    username: guest
    password: guest
 cloud:
   stream:
     instance-count: 2 # 消费者总数
     instance-index: 1 # 当前消费者的索引
     bindings:
       input:
         destination: greetings
         group: service-a
         consumer:
           partitioned: true # 开启分区支持

生产者的代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.core.MessageSource;
import org.springframework.messaging.support.GenericMessage;

@EnableBinding(value = Source.class)
public class SinkSender {

    private static final Logger LOGGER = LoggerFactory.getLogger(SinkSender.class);

    @Bean
    @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "2000"))
    public MessageSource<String> timerMessageSource() {
        return () -> new GenericMessage<>("{\"name\":\"kevin\",\"age\":18}");
    }

}

生产者的配置:

spring:
  rabbitmq:
    host: 192.168.99.100
    port: 5672
    username: guest
    password: guest
  cloud:
    stream:
      bindings:
        output:
          destination: greetings
          producer:
            partition-key-expression: payload # 配置分区键的表达式规则
            partition-count: 2 # 配置消息分区的数量

我们可以再次启动这两个应用,同时启动两个消费者。但需要注意的是,要为消费者指定不同的实例索引号,这样当同一个消息被发送给消费组时,可以发现只有一个消费实例在接收和处理这些相同的消息。

在这里插入图片描述

在这里插入图片描述

源代码参考:https://gitee.com/cckevincyh/cloud-stream-demo/tree/demo10/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值