Rocketmq4.7 生产者、push消费者和pull消费者 java客户端简单使用和一些注意事项

maven引用

        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.7.0</version>
        </dependency>
        <!--一个好用的工具包,可以不引入-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.0</version>
        </dependency>

 

说明

  不管是生产者还是消费者,都有很多参数可以配置,rocketmq命名比较好,基本可以从参数名上判断具体作用,还有注释可以看。

下面例子中只给出了常用的一些参数设置。更多参数可自行探索。

 

 简单生产者实现

注意:

1、NamesrvAddr参数在多个节点时,用英文分号分隔,例: 192.168.9.58:9876;192.168.9.59:9876

import cn.hutool.core.util.RandomUtil;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;

public class Producer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        producer.setNamesrvAddr("127.0.0.1:9876");
        //发送超时时间,默认3000 单位ms
        producer.setSendMsgTimeout(5000);
        producer.start();

        try {
            Message msg = new Message("TestTopic",// topic
                    "177",                       // tag 可以为空,用以简单的筛选。
                    RandomUtil.randomString(8),  // key 可以为空,可用以查询。
                    ("test" + RandomUtil.randomString(8)).getBytes());    // body ,我常将对象转json再获取byte[] 进行传输。
            SendResult send = producer.send(msg);
            if (send.getSendStatus().equals(SendStatus.SEND_OK)) {
                //发送成功处理
            }else {
                //发送失败处理
            }
        } catch (Exception e) {
            //发送失败处理
            e.printStackTrace();
        }
        //正式环境不要发完就就shutdown,要在应用退出时再shutdown。
        producer.shutdown();
    }
}

多线程加批量生产者模拟实现

注意:

1、批量发送时,topic必须为同一个,否则发送会报异常。

2、批量发送相较于单条发送速度提升很大。

import cn.hutool.core.util.RandomUtil;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class Producer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        producer.setNamesrvAddr("127.0.0.1:9876");
        //发送超时时间,默认3000 单位ms
        producer.setSendMsgTimeout(5000);
        producer.start();

        int threadCount = 20;
        int forCount = 100000;
        CountDownLatch latch = new CountDownLatch(threadCount);
        long start = System.currentTimeMillis();
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    List<Message> list = new ArrayList<>();
                    for (int j = 0; j < forCount; j++) {
                        try {
                            Message msg = new Message("TestTopic",// topic
                                    "177",                       // tag
                                    RandomUtil.randomString(8),                       // key
                                    ("test" + RandomUtil.randomString(8)).getBytes());    // body
                            list.add(msg);
                            if (list.size() >= 100) {
                                SendResult send = producer.send(list);
                                if (send.getSendStatus().equals(SendStatus.SEND_OK)) {
                                    //发送成功处理
                                    list.clear();
                                }else {
                                    //发送失败处理
                                }
                            }
                        } catch (Exception e) {
                            //发送失败处理
                            e.printStackTrace();
                        }
                    }
                    if (list.size() > 0) {
                        SendResult send = producer.send(list);
                        if (!send.getSendStatus().equals(SendStatus.SEND_OK)) {
                            System.out.println(send);
                        }
                        list.clear();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            }).start();
        }
        latch.await();
        long hs = System.currentTimeMillis() - start;
        System.out.println(hs);

        long speed = (threadCount * forCount) / (hs >= 0 ? 1 : hs / 1000);
        System.out.println("速度" + speed);
        //正式环境不要发完就就shutdown,要在应用退出时再shutdown。
        producer.shutdown();
    }
}

push消费者

import cn.hutool.core.lang.Console;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;

public class PushConsumer {
    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("PushConsumerGroupName");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        //一个GroupName第一次消费时的位置
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
        consumer.setConsumeThreadMin(20);
        consumer.setConsumeThreadMax(20);
        //要消费的topic,可使用tag进行简单过滤
        consumer.subscribe("TestTopic", "*");
        //一次最大消费的条数
        consumer.setConsumeMessageBatchMaxSize(100);
        //消费模式,广播或者集群,默认集群。
        consumer.setMessageModel(MessageModel.CLUSTERING);
        //在同一jvm中 需要启动两个同一GroupName的情况需要这个参数不一样。
        consumer.setInstanceName("InstanceName");
        //配置消息监听
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            try {
                //业务处理
                msgs.forEach(msg -> {
                    Console.log(msg);
                });
            } catch (Exception e) {
                System.err.println("接收异常" + e);
                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });
        consumer.start();
        System.out.println("Consumer Started.");
    }
}

pull消费者

从4.6之后,提供了DefaultLitePullConsumer  大大简化了pull的操作。以下为新实现,4.6之前的版本不支持。

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Console;
import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class PullConsumer {
    private static boolean runFlag = true;
    public static void main(String[] args) throws Exception {
        DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("PullConsumerGroupName");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        //要消费的topic,可使用tag进行简单过滤
        consumer.subscribe("TestTopic", "*");
        //一次最大消费的条数
        consumer.setPullBatchSize(100);
        //无消息时,最大阻塞时间。默认5000 单位ms
        consumer.setPollTimeoutMillis(5000);
        consumer.start();
        while (runFlag){
            try {
                //拉取消息,无消息时会阻塞 
                List<MessageExt> msgs = consumer.poll();
                if (CollUtil.isEmpty(msgs)){
                    continue;
                }
                //业务处理
                msgs.forEach(msg-> Console.log(new String(msg.getBody())));
                //同步消费位置。不执行该方法,应用重启会存在重复消费。
                consumer.commitSync();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        consumer.shutdown();
    }
}
上一篇:Kafka事务特性详解


下一篇:kafka 自定义分区类和拦截器