RocketMQ极简入门-RocketMQ消息批量发送

简介: 批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB,如果超过可以有2种处理方案:1.将消息进行切割成多个小于4M的内容进行发送2.修改4M的限制改成更大可以设置Producer的maxMessageSize属性修改配置文件中的maxMessageSize属性

使用场景

如果消息过多,每次发送消息都和MQ建立连接,无疑是一种性能开销,批量消息可以把消息打包批量发送,批量发送消息能显著提高传递小消息的性能。

批量消息概述

批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,而且不能是延时消息。此外,这一批消息的总大小不应超过4MB,如果超过可以有2种处理方案:

1.将消息进行切割成多个小于4M的内容进行发送

2.修改4M的限制改成更大

  • 可以设置Producer的maxMessageSize属性
  • 修改配置文件中的maxMessageSize属性

对于消费者而言Consumer的MessageListenerConcurrently监听接口的consumeMessage()方法的第一个参数为消息列 表,但默认情况下每次只能消费一条消息,可以通过:Consumer的pullBatchSize属性设置消息拉取数量(默认32),可以通过设置consumeMessageBatchMaxSize属性设置消息一次消费数量(默认1)。

[注意]:pullBatchSize 和 consumeMessageBatchMaxSize并不是设置越大越好,一次拉取数据量太大会导致长时间等待,性能降低。而且消息处理失败同一批消息都会失败,然后进行重试,导致消费时长增加。增加没必要的重试次数。

批量消息实战

生产者

我们需要做什么

  • 定义消息切割器切割消息
  • 发送消息把消息切割之后,进行多次批量发送

定义消息切割器

//消息切割器,按照4M大小写个publicclassListSplitterimplementsIterator<List<Message>> {
privatefinalintSIZE_LIMIT=1024*1024*4;
privatefinalList<Message>messages;
privateintcurrIndex;
publicListSplitter(List<Message>messages) { 
this.messages=messages;
    }
@OverridepublicbooleanhasNext() {
returncurrIndex<messages.size(); 
    }
@OverridepublicList<Message>next() { 
intstartIndex=getStartIndex();
intnextIndex=startIndex;
inttotalSize=0;
for (; nextIndex<messages.size(); nextIndex++) {
Messagemessage=messages.get(nextIndex); 
inttmpSize=calcMessageSize(message);
if (tmpSize+totalSize>SIZE_LIMIT) {
break; 
            } else {
totalSize+=tmpSize; 
            }
        }
List<Message>subList=messages.subList(startIndex, nextIndex); 
currIndex=nextIndex;
returnsubList;
    }
privateintgetStartIndex() {
MessagecurrMessage=messages.get(currIndex); 
inttmpSize=calcMessageSize(currMessage); 
while(tmpSize>SIZE_LIMIT) {
currIndex+=1;
Messagemessage=messages.get(currIndex);
tmpSize=calcMessageSize(message);
        }
returncurrIndex; 
    }
privateintcalcMessageSize(Messagemessage) {
inttmpSize=message.getTopic().length() +message.getBody().length;
Map<String, String>properties=message.getProperties();
for (Map.Entry<String, String>entry : properties.entrySet()) {
tmpSize+=entry.getKey().length() +entry.getValue().length(); 
        }
tmpSize=tmpSize+20; // 增加⽇日志的开销20字节returntmpSize; 
    }
}

消息发送

publicclassBatchProducer {
//演示消息同步发送publicstaticvoidmain(String[] args) throwsInterruptedException, RemotingException, MQClientException, MQBrokerException {
//生产者DefaultMQProducerproducer=newDefaultMQProducer("batch-producerGroup");
//设置name server地址producer.setNamesrvAddr("127.0.0.1:9876");
//设置最大消息大小,默认4Mproducer.setMaxMessageSize(1024*1024*4);
//启动producer.start();
//===========准备消息==========================================================List<Message>messages=newArrayList<>();
for (longi=0 ; i<10000 ; i++){
//添加内容byte[] bytes= ("批量消息".getBytes(CharsetUtil.UTF_8));
Messagemessage=newMessage("topic-order-batch","product-order-batch",bytes);
message.setKeys("key-"+i);
messages.add(message);
        }
//===========切割消息==========================================================//把大的消息分裂成若干个小的消息ListSplittersplitter=newListSplitter(messages);
while (splitter.hasNext()) {
try {
//安装4m切割消息List<Message>listItem=splitter.next();
//发送消息SendResultsendResult=producer.send(listItem);
System.out.println(sendResult);
            } catch (Exceptione) {
e.printStackTrace();
//处理error            }
        }
producer.shutdown();
    }
}

消费者

我们要做什么

  • 可以指定消息拉取数量和消费数量
publicclassBatchConsumer {
publicstaticvoidmain(String[] args) throwsMQClientException {
//创建消费者DefaultMQPushConsumerdefaultMQPushConsumer=newDefaultMQPushConsumer("batch-consumerGroup");
//设置name server 地址defaultMQPushConsumer.setNamesrvAddr("127.0.0.1:9876");
//从开始位置消费defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
//批量拉取消息数量,默认32defaultMQPushConsumer.setPullBatchSize(32);
//每次消费条数,默认1defaultMQPushConsumer.setConsumeMessageBatchMaxSize(10);
//订阅defaultMQPushConsumer.subscribe("topic-order-batch","product-order-batch");
defaultMQPushConsumer.registerMessageListener(newMessageListenerConcurrently() {
@OverridepublicConsumeConcurrentlyStatusconsumeMessage(List<MessageExt>list, ConsumeConcurrentlyContextconsumeConcurrentlyContext) {
list.forEach(message->{
System.out.println(message+" ; "+newString(message.getBody(), CharsetUtil.UTF_8));
                });
returnConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
defaultMQPushConsumer.start();
    }
}


相关实践学习
5分钟轻松打造应对流量洪峰的稳定商城交易系统
本实验通过SAE极速部署一个微服务电商商城,同时结合RocketMQ异步解耦、削峰填谷的能力,带大家体验面对流量洪峰仍旧稳定可靠的商城交易系统!
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
Heron
+关注
目录
打赏
0
1
0
0
15
分享
相关文章
一文带你从入门到实战全面掌握RocketMQ核心概念、架构部署、实践应用和高级特性
本文详细介绍了分布式消息中间件RocketMQ的核心概念、部署方式及使用方法。RocketMQ由阿里研发并开源,具有高性能、高可靠性和分布式特性,广泛应用于金融、互联网等领域。文章从环境搭建到消息类型的实战(普通消息、延迟消息、顺序消息和事务消息)进行了全面解析,并对比了三种消费者类型(PushConsumer、SimpleConsumer和PullConsumer)的特点与适用场景。最后总结了使用RocketMQ时的关键注意事项,如Topic和Tag的设计、监控告警的重要性以及性能与可靠性的平衡。通过学习本文,读者可掌握RocketMQ的使用精髓并灵活应用于实际项目中。
466 7
 一文带你从入门到实战全面掌握RocketMQ核心概念、架构部署、实践应用和高级特性
MQTT 5.0 报文(Packets)入门指南
MQTT 控制报文是 MQTT 数据传输的最小单元。MQTT 客户端和服务端通过交换控制报文来完成它们的工作,比如订阅主题和发布消息。
EMQ
912 54
MQTT 5.0 报文(Packets)入门指南
分享一下rocketmq入门小知识
分享一下rocketmq入门小知识
109 0
分享一下rocketmq入门小知识
App Inventor 2 MQTT拓展入门(保姆级教程)
本文演示的是App和一个测试客户端进行消息交互的案例,实际应用中,我们的测试客户端可以看着是任意的、支持MQTT协议的硬件,通过订阅及发布消息,联网硬件与我们的App进行双向数据通信,以实现万物互联的智能控制效果。
582 2
RabbitMQ在Java中的完美实现:从入门到精通
本文由木头左介绍如何在Java项目中使用RabbitMQ。RabbitMQ是开源的AMQP实现,支持多种客户端,适合分布式系统中的消息传递。首先需安装Erlang和RabbitMQ,接着在Java项目中添加RabbitMQ客户端库依赖。通过创建连接工厂和连接,建立与RabbitMQ的通信,并展示了创建连接和通道的代码示例。
RabbitMQ入门指南(十一):延迟消息-延迟消息插件
RabbitMQ是一个高效、可靠的开源消息队列系统,广泛用于软件开发、数据传输、微服务等领域。本文主要介绍了DelayExchange插件、延迟消息插件实现延迟消息等内容。
1446 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问