RocketMQ主要由Producer、Broker、Consumer三部分组成,其中Producer负责生产消息,Consumer负责消费消息,Broker负责存储消息。Broker在实际部署过程中对应一台服务器,每个Broker可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的Broker。MessageQueue用于存储消息的物理地址,每个Topic中的消息地址存储于多个MessageQueue中。ConsumerGroup由多个Consumer实例构成。
负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。
负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。
表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位。
消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。
名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的BrokerIP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程。
Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。
同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。
同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。
集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息。
广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。
普通顺序消费模式下,消费者通过同一个消息队列(Topic分区,称作Message Queue)收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。
严格顺序消息模式下,消费者收到的所有消息均是有顺序的。
消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题。RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能。
为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.StandardCharsets;
public class RocketMqProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("helloGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "helloTopic";
//发送
for (int i = 0; i < 10; i++) {
Message msg = new Message(topic,("RocketMQ普通消息"+i).getBytes(StandardCharsets.UTF_8));
//发送完成之后会返回响应结果
SendResult result = producer.send(msg);
System.out.println("发送状态:" + result.getSendStatus());
}
System.out.println("消息发送完毕");
//关闭资源
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("helloTopic","*");
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:"+Thread.currentThread()+",消息的内容:"+new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.StandardCharsets;
public class RocketMqProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("helloGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "helloTopic";
//发送
for (int i = 0; i < 10; i++) {
Message msg = new Message(topic,("RocketMQ普通消息"+i).getBytes(StandardCharsets.UTF_8));
//发送完成之后会返回响应结果
SendResult result = producer.send(msg);
System.out.println("发送状态:" + result.getSendStatus());
}
System.out.println("消息发送完毕");
//关闭资源
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.Charset;
public class SyncProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("syncGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
producer.start();
//设置消息发送的目的地Topic
String topic = "syncTopic";
//发送消息
Message message = new Message(topic, "Rocket sync".getBytes(Charset.defaultCharset()));
//异步发送,需要传递异步回调的对象
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("消息存储状态:" + sendResult.getSendStatus());
}
@Override
public void onException(Throwable throwable) {
System.out.println("消息发送出现异常");
}
});
System.out.println("消息发送完毕.");
//关闭资源
//producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.Charset;
public class OneProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("oneGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
producer.start();
//设置消息发送的目的地Topic
String topic = "oneTopic";
//发送消息
Message message = new Message(topic, "One Message".getBytes(Charset.defaultCharset()));
//一次性发送,需要传递异步回调的对象
producer.send(message);
System.out.println("消息发送完毕.");
//关闭资源
//producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.StandardCharsets;
public class RocketMqProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("helloGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "helloTopic";
//发送
for (int i = 0; i < 10; i++) {
Message msg = new Message(topic,("RocketMQ普通消息"+i).getBytes(StandardCharsets.UTF_8));
//发送完成之后会返回响应结果
SendResult result = producer.send(msg);
System.out.println("发送状态:" + result.getSendStatus());
}
System.out.println("消息发送完毕");
//关闭资源
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("helloTopic","*");
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:"+Thread.currentThread()+",消息的内容:"+new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQBroadcastConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("helloTopic","*");
//设置发送模式
consumer.setMessageModel(MessageModel.BROADCASTING);
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:"+Thread.currentThread()+",消息的内容:"+new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("helloTopic","*");
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:"+Thread.currentThread()+",消息的内容:"+new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import com.lihailin.gulimall.order.entity.OrderStep;
import com.lihailin.gulimall.order.util.OrderUtil;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQOrderProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("orderProducerGroup");
producer.setNamesrvAddr("192.168.152.165:9876");
producer.start();
String topic = "orderTopic";
MessageQueueSelector selector = new MessageQueueSelector() {
@Override
public MessageQueue select(List list, Message message, Object o) {
int size = list.size();
long temp = (long) o;
return list.get((int) temp % size);
}
};
List orderStepList = OrderUtil.buildOrders();
for (OrderStep orderStep : orderStepList) {
Message message = new Message(topic, orderStep.toString().getBytes(Charset.defaultCharset()));
producer.send(message, selector, orderStep.getOrderId());
System.out.println(orderStep);
}
producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.*;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQOrderConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup2");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("helloTopic","*");
//设置从头开始消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
//设置消息的监听器
consumer.setMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:" + Thread.currentThread() + ",消息的内容:" + new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeOrderlyStatus.SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.Charset;
public class DelayMQProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("helloGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "helloTopic";
//发送
for (int i = 0; i < 10; i++) { // Charset.defaultCharset()
Message msg = new Message(topic,("RocketMQ======"+i).getBytes(Charset.defaultCharset()));
//发送完成之后会返回响应结果
msg.setDelayTimeLevel(5);
SendResult result = producer.send(msg);
System.out.println("发送状态:" + result.getSendStatus());
}
System.out.println("消息发送完毕");
//关闭资源
producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.Charset;
public class RocketMqTagProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("tagProducerGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "tagFilterTopic";
Message tag1 = new Message(topic, "TagA", ("消息A").getBytes(Charset.defaultCharset()));
Message tag2 = new Message(topic, "TagB", ("消息B").getBytes(Charset.defaultCharset()));
Message tag3 = new Message(topic, "TagC", ("消息C").getBytes(Charset.defaultCharset()));
producer.sendOneway(tag1);
producer.sendOneway(tag2);
producer.sendOneway(tag3);
System.out.println("消息发送完毕");
//关闭资源
producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.*;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQTagConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup3");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("tagFilterTopic","TagA || TagC");
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:" + Thread.currentThread() + ",消息的内容:" + new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import java.nio.charset.Charset;
public class RocketMqSqlTagProducer {
public static void main(String[] args) throws Exception {
// 定义一个生产者对象
DefaultMQProducer producer = new DefaultMQProducer("sqlTagProducerGroup");
//连接nameServer
producer.setNamesrvAddr("192.168.152.165:9876");
//启动生产者
producer.start();
//设置消息发送的目的地Topic
String topic = "sqlTagFilterTopic";
Message tag1 = new Message(topic, ("小红,年龄:34,体重:45").getBytes(Charset.defaultCharset()));
tag1.putUserProperty("age","34");
tag1.putUserProperty("weight","45");
Message tag2 = new Message(topic, ("小明,年龄:25,体重:45").getBytes(Charset.defaultCharset()));
tag2.putUserProperty("age","25");
tag2.putUserProperty("weight","45");
Message tag3 = new Message(topic, ("小蓝,年龄:40,体重:70").getBytes(Charset.defaultCharset()));
tag3.putUserProperty("age","40");
tag3.putUserProperty("weight","70");
producer.sendOneway(tag1);
producer.sendOneway(tag2);
producer.sendOneway(tag3);
System.out.println("消息发送完毕");
//关闭资源
producer.shutdown();
}
}
package com.lihailin.gulimall.order.controller;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.MessageSelector;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import java.nio.charset.Charset;
import java.util.List;
public class RocketMQSqlTagConsumer {
public static void main(String[] args) throws Exception {
//定义消息消费者(在同一个JVM中,消费者的组名不能重复)
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("helloConsumerGroup3");
//设置nameServer地址
consumer.setNamesrvAddr("192.168.152.165:9876");
//设置订阅的主题
consumer.subscribe("sqlTagFilterTopic", MessageSelector.bySql("age>23 and weight<60"));
//设置消息的监听器
consumer.setMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : list) {
System.out.println("线程:" + Thread.currentThread() + ",消息的内容:" + new String(msg.getBody(), Charset.defaultCharset()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动的消费者
consumer.start();
}
}
在broker.conf配置文件中加
enablePropertyFilter = true