rocketmq_005_批量发送

 发送方

public class SyncBatchProducer {
    public static void main(String[] args) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
        //        1.创建消息生产者,并且制定生产者组名
        DefaultMQProducer producer = new DefaultMQProducer("group1");
//        设置超时时间
        producer.setSendMsgTimeout(10000);
//        2.指定namesrv地址
        producer.setNamesrvAddr("192.168.48.128:9876;192.168.48.137:9876");
//        producer.setNamesrvAddr("47.96.165.93:9876;106.52.131.197:9876");
//        3.启动producer
        try {
            producer.start();
        } catch (
                MQClientException e) {
            e.printStackTrace();
        }
//      4.将消息对象放到集合中
        List<Message> msgs = new ArrayList<>();
        Message msg1 = new Message("batchTopic","batch",("helloworld"+1).getBytes());
        Message msg2 = new Message("batchTopic","batch",("helloworld"+2).getBytes());
        Message msg3 = new Message("batchTopic","batch",("helloworld"+3).getBytes());
        msgs.add(msg1);
        msgs.add(msg2);
        msgs.add(msg3);
//      5.发送集合msgs
        SendResult result = producer.send(msgs);
        SendStatus status = result.getSendStatus();
        System.out.println("发送结果:"+status);
        TimeUnit.SECONDS.sleep(1);
//         关闭producer
        producer.shutdown();
    }
}

消费方 

public class BatchConsumer {
    public static void main(String[] args) {
        consumer();
    }

    public static void consumer(){
        //        1 创建消费者Consumer ,并确定消费者组名
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
//        2 指定NameServer地址
        consumer.setNamesrvAddr("192.168.48.128:9876;192.168.48.137:9876");
//        consumer.setNamesrvAddr("106.52.131.197:9876;47.96.165.93:9876");
        try {
//            3 订阅主题Topic和Tag
            consumer.subscribe("batchTopic","*");
//        4 设置回调函数,处理消息
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                //            接受消息内容
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                    for(MessageExt msg:msgs){
                        System.out.println(new String(msg.getBody()));
                    }
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
//        5 启动消息内容
            consumer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }
}

注意

1、发送方的批量消息对象必须topic一致,否则报以下异常

虽然topic必须一致,但tag可以变动2、消费方只能使用负载均衡模式消费,不支持广播

3、不支持延迟消费

4、批量发送总大小不超4m,如果4m以上就得分析消息(目的是让部分总数据不高于4m的消息发送出去,其余过滤掉,当然还有其它方式,比如分割数据,批次发送),代码如下:

4.1、创建一个工具类来分析集合中的消息

class BatchProducerLargeFileUtil implements Iterator<List<Message>> {
    private final int SIZE_LIMTI = 1024*1024*4;
    private final List<Message> messages;
    private int currIndex;
    public BatchProducerLargeFileUtil(List<Message> messages){
        this.messages = messages;
    }
    public boolean hasNext(){
        return currIndex < messages.size();
    }
    public List<Message> next(){
        int nextIndex = currIndex;
        int totalSize = 0;
        for(;nextIndex < messages.size();nextIndex++){
            Message message = messages.get(nextIndex);
            //每条消息的数据大小=topic.length + message.getBody().length + message的属性值,即properties对象的存储数据量 + 日志20个字节
            int tmpSize = message.getTopic().length()+message.getBody().length; //topic.length + message.getBody().length
            Map<String,String> properties = message.getProperties();            //message的属性值,即properties对象的存储数据量
            for(Map.Entry<String,String> entry:properties.entrySet()){
                tmpSize += entry.getKey().length()+entry.getValue().length();
            }
            tmpSize += 20;  //日志20个字节                                       //日志20个字节
            if(tmpSize>SIZE_LIMTI){
//                单个消息超过了最大的限度
//                忽略,否则会阻塞分裂进程
                if(nextIndex - currIndex==0){
//                    假如下一个子列表没有元素,则添加这个子列表然后退出循环,否则只是退出循环
                    nextIndex++;
                }
                break;
            }
            if(tmpSize+totalSize>SIZE_LIMTI){
                break;
            } else {
                totalSize +=tmpSize;
            }
        }

        List<Message> subList = messages.subList(currIndex,nextIndex);
        currIndex = nextIndex;
        return subList;
    }
}

4.2、发送时调用工具类来分析消息对象 

public class SyncBatchLargeFileProducer {
    public static void main(String[] args) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
        //        1.创建消息生产者,并且制定生产者组名
        DefaultMQProducer producer = new DefaultMQProducer("group1");
//        设置超时时间
        producer.setSendMsgTimeout(10000);
//        2.指定namesrv地址
        producer.setNamesrvAddr("192.168.48.128:9876;192.168.48.137:9876");
//        producer.setNamesrvAddr("47.96.165.93:9876;106.52.131.197:9876");
//        3.启动producer
        try {
            producer.start();
        } catch (
                MQClientException e) {
            e.printStackTrace();
        }
//      4.将消息对象放到集合中
        List<Message> msgs = new ArrayList<>();
        Message msg1 = new Message("batchTopic","batch",("helloworld"+1).getBytes());
        Message msg2 = new Message("batchTopic","batch1",("helloworld"+2).getBytes());
        Message msg3 = new Message("batchTopic","batch2",("helloworld"+3).getBytes());
        msgs.add(msg1);
        msgs.add(msg2);
        msgs.add(msg3);
        BatchProducerLargeFileUtil batchConsumerLargeFileUtil = new BatchProducerLargeFileUtil(msgs);
        while (batchConsumerLargeFileUtil.hasNext()){
            try{
                List<Message> listItem = batchConsumerLargeFileUtil.next();
                //      5.发送集合msgs
                SendResult result = producer.send(listItem);
                SendStatus status = result.getSendStatus();
                System.out.println("发送结果:"+status);
                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                //         关闭producer
                producer.shutdown();
            }
        }
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值