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
本文来自博客园,作者:Jason,转载请注明原文链接:https://www.cnblogs.com/jason207010/p/18432862
浙公网安备 33010602011771号