RocketMQ有2种常见的消费模式,分别是DefaultMQPushConsumer和DefaultMQPullConsumer模式。两种模式其本质都是拉取消息,只是实现机制不一样。
DefaultMQPushConsumer(推荐使用):consumer向broker发出请求,保持了一种长链接,broker会每5秒会检测一次是否有消息,如果有消息,则将消息推送给consumer。broker会主动记录消息消费的偏移量。
DefaultMQPullConsumer:consumer通过本地定时任务主动去broker拉取数据,消息的及时性差,而且需要手动记录消息消费的偏移量信息 ,所以在工作中多数情况推荐使用Push模式。
RocketMQ发送的消息默认会存储到4个队列中,当然创建几个队列存储数据,可以自己定义。
生产者:
public class Producer {
//指定namesrv地址
private static String NAMESRV_ADDRESS = "127.0.0.1:9876";
public static void main(String[] args) throws Exception {
//创建一个DefaultMQProducer,需要指定消息发送组
DefaultMQProducer producer = new DefaultMQProducer("My_Producer_Group");
//指定Namesvr地址
producer.setNamesrvAddr(NAMESRV_ADDRESS);
//启动Producer
producer.start();
//创建消息
Message message = new Message(
"My_Topic", //主题
"Tag1", //标签,可以用来做过滤
"Key1", //唯一标识,可以用来查找消息
"hello_rocketmq_test_message".getBytes() //要发送的消息字节数组
);
//发送消息
//******当不指定具体队列,roceket默认会将消息随机发送到4个队列中,各自队列只保证自己消息的顺序。所以无法保证全局消息的有序性
//可在控制台看到消息均随机被发送到4个队列
SendResult result = producer.send(message);
//关闭producer
producer.shutdown();
}
}
消费者:
public class Consumer {
//指定namesrv地址
private static String NAMESRV_ADDRESS = "127.0.0.1:9876";
public static void main(String[] args) throws MQClientException {
//创建DefaultMQPushConsumer
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("Test_Quick_Consumer_Name");
//设置namesrv地址
consumer.setNamesrvAddr(NAMESRV_ADDRESS);
//设置要读取的topic
consumer.subscribe(
"My_Topic", //指定要读取的消息主题
"Tag1"); //指定要读取的消息过滤信息,多个标签数据,则可以输入"tag1 || tag2 || tag3"
//创建消息监听
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
try {
//获取第1个消息
MessageExt message = msgs.get(0);
//获取主题
String topic = message.getTopic();
//获取标签
String tags = message.getTags();
//获取消息
String result = new String(message.getBody(),"UTF-8");
System.out.println("topic:"+topic+",tags:"+tags+",result:"+result);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
//消息重试
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
//消息消费成功
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动消费监听
consumer.start();
}
}