Spring Boot 集成 RabbitMQ 批量发送、消费消息

1. Spring Boot 集成 RabbitMQ 批量发送、消费消息

1.1. 版本说明

构件 版本
spring-boot 2.7.18
spring-boot-starter-amqp 2.7.18

1.2. Spring 配置

spring:
application:
name: spring-rabbit-batch-demo
rabbitmq:
addresses: 127.0.0.1:5672
username: admin
password: admin
virtual-host: /

1.3. 定义常量

public class RabbitBatchConstants {
public static final String QUEUE_1 = "spring-rabbit-batch-demo-queue-1";
public static final String EXCHANGE_1 = "spring-rabbit-batch-demo-exchange-1";
public static final String QUEUE_2 = "spring-rabbit-batch-demo-queue-2";
public static final String EXCHANGE_2 = "spring-rabbit-batch-demo-exchange-2";
}

1.4. 配置交换机和队列

@Configuration
@Slf4j
public class RabbitBatchConfiguration {
@Bean
public Queue queue1() {
return QueueBuilder.durable(RabbitBatchConstants.QUEUE_1).build();
}
@Bean
public FanoutExchange exchange1() {
return ExchangeBuilder.fanoutExchange(RabbitBatchConstants.EXCHANGE_1).durable(true).build();
}
@Bean
public Queue queue2() {
return QueueBuilder.durable(RabbitBatchConstants.QUEUE_2).build();
}
@Bean
public FanoutExchange exchange2() {
return ExchangeBuilder.fanoutExchange(RabbitBatchConstants.EXCHANGE_2).durable(true).build();
}
@Bean
public Binding binding1() {
return BindingBuilder.bind(queue1()).to(exchange1());
}
@Bean
public Binding binding2() {
return BindingBuilder.bind(queue2()).to(exchange2());
}
}

1.5. 定义 BatchingRabbitTemplate 工厂

org.springframework.amqp.rabbit.core.BatchingRabbitTemplate 提供了批量发送消息的 API,但是一个 BatchingRabbitTemplate 实例只能发送同一交换机或 Routing Key 的消息,因此需要一个工厂类,针对同一交换机生成一个 BatchingRabbitTemplate 实例。

定义 TaskScheduler:

@Bean(name = "rabbitBatchTaskScheduler")
TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(Runtime.getRuntime().availableProcessors() * 2);
threadPoolTaskScheduler.setThreadNamePrefix("rabbit-batch-");
threadPoolTaskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskScheduler.initialize();
return threadPoolTaskScheduler;
}

定义 BatchingRabbitTemplate 工厂:

@Component
public class BatchingRabbitTemplateFactory implements Lifecycle {
@Resource
private ConnectionFactory connectionFactory;
@Resource(name = "rabbitBatchTaskScheduler")
private TaskScheduler taskScheduler;
private Map<String, BatchingRabbitTemplate> batchingRabbitTemplateMap = new ConcurrentHashMap<>();
public BatchingRabbitTemplate getBatchingRabbitTemplate(String exchange) {
return batchingRabbitTemplateMap.computeIfAbsent(exchange, exchangeName -> {
//批量发送 100 条消息,假设 1 条消息大小 1Kb,缓存 1000 条消息,1 秒超时
return new BatchingRabbitTemplate(connectionFactory, new SimpleBatchingStrategy(100, 1024 * 1000, 1000L), taskScheduler);
});
}
@Override
public void start() {
}
@Override
public void stop() {
batchingRabbitTemplateMap.forEach((exchange, batchingRabbitTemplate) -> batchingRabbitTemplate.stop());
}
@Override
public boolean isRunning() {
return true;
}
}

1.6. 配置批量消费消息的 RabbitListenerContainerFactory

@Bean(name = "batchRabbitListenerContainerFactory")
SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
//启用批量消费消费
factory.setBatchListener(true);
//批量消费 100 条消息
factory.setBatchSize(100);
return factory;
}

1.7. 测试

@Component
@Slf4j
public class SpringRabbitBatchDemo implements ApplicationRunner {
@Resource
private BatchingRabbitTemplateFactory batchingRabbitTemplateFactory;
@Override
public void run(ApplicationArguments args) throws Exception {
String payload1 = "hello, queue 1";
for (int i = 0; i < 100; i++) {
batchingRabbitTemplateFactory.getBatchingRabbitTemplate(EXCHANGE_1).convertAndSend(EXCHANGE_1, null, payload1);
}
log.info("send 100 messages, exchange: {}, payload: {}", EXCHANGE_1, payload1);
String payload2 = "hello, queue 2";
for (int i = 0; i < 2; i++) {
batchingRabbitTemplateFactory.getBatchingRabbitTemplate(EXCHANGE_2).convertAndSend(EXCHANGE_2, null, payload2);
}
log.info("send 2 messages, exchange: {}, payload: {}", EXCHANGE_2, payload2);
}
/**
* 消息批量消费
* @param messages
*/
@RabbitListener(queues = {RabbitBatchConstants.QUEUE_1}, containerFactory = "batchRabbitListenerContainerFactory")
public void listen1(List<Message<String>> messages) {
log.info(
"queue 1 received {} messages",
messages.size()
);
}
/**
* 消息单条消费
* @param message
*/
@RabbitListener(queues = {RabbitBatchConstants.QUEUE_2})
public void listen2(Message<String> message) {
log.info("queue 2 received a message");
}
}

启动程序,控制台将输出:

send 100 messages, exchange: spring-rabbit-batch-demo-exchange-1, payload: hello, queue 1
send 2 messages, exchange: spring-rabbit-batch-demo-exchange-2, payload: hello, queue 2
queue 1 received 100 messages
queue 2 received a message
queue 2 received a message
posted @   Jason207010  阅读(586)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示