1 消费模式
1.1 Pull 模式
- 自主选择
Message Queue和offset进行消息拉取,用户拉取消息时,需要用户自己来决定拉去哪个队列从哪个offset开始,拉取多少消息。 - 用户自己维护
offsetStore,具体的消费进度roccketMQ不会进行存储,用户可以存入 redis 或者调用 MQ 接口保存。 - 用户大都采用 Push 模式。
1.2 Push 模式
DefaultMQPushConsumer 是 Push 方式的默认实现,其中 Push 方式是基于 Pull 模式,拉取后再次拉取消息,然后主动推送给消费者,所以是 Push 模式。
2 Push 消费者启动流程
push 模式的消费者启动实例如下,实例化一个 DefaultMQPushConsumer ,设置其中的核心属性。完成消费者启动。
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("quickstart");
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TopicTest", "*");
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeConcurrentlyContext context) {
System.out.println("===开始消费===");
for (MessageExt msg : msgs) {
System.out.println("当前线程:" + Thread.currentThread().getName() + "========message body: "
+ new String(msg.getBody(), StandardCharsets.UTF_8) + ", 接收时间:" + new Date());
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.printf("Consumer Started.%n");
2.1 初始化消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("quickstart");:初始化消费者,采用默认的 AllocateMessageQueueAveragely 平均分配消息队列。
/**
* Constructor specifying consumer group.
* 构造方法,默认分配消息队列策略为 AllocateMessageQueueAveragely
* @param consumerGroup Consumer group.
*/
public DefaultMQPushConsumer(final String consumerGroup) {
this(consumerGroup, null, new AllocateMessageQueueAveragely());
}
2.2 订阅主题消息
org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl#subscribe:消费者订阅主题消息,其中通过表达式进行过滤。
/**
* 订阅满足表达式过滤的主题消息
* @param topic 主题消息
* @param subExpression 表达式过滤
*/
public void subscribe(String topic, String subExpression) throws MQClientException {
// 创建订阅数据
SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(),
topic, subExpression);
// 设置订阅的信息
this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);
// 通过心跳同步将 Consumer 订阅信息到 Broker
if (this.mQClientFactory != null) {
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();
}
}
org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData: 订阅的信息。
public class SubscriptionData implements Comparable<SubscriptionData> {
// 订阅所有的
public final static String SUB_ALL = "*";
private boolean classFilterMode = false;
// 主题
private String topic;
// 订阅 tag
private String subString;
// tag 集合
private Set<String> tagsSet = new HashSet<String>();
private Set<Integer> codeSet = new HashSet<Integer>();
private long subVersion = System.currentTimeMillis();
private String expressionType = ExpressionType.TAG;
}
org.apache.rocketmq.common.filter.FilterAPI#buildSubscriptionData:根据 consumerGroup、topic 信息构建订阅的信息
public static SubscriptionData buildSubscriptionData(final String consumerGroup, String topic,
String subString) throws Exception {
SubscriptionData subscriptionData = new SubscriptionData();
subscriptionData.setTopic(topic);
subscriptionData.setSubString(subString);
// 如果不设置订阅的 tag,那么默认为 topic 下所有的 tag
if (null == subString || subString.equals(SubscriptionData.SUB_ALL) || subString.length() == 0) {
subscriptionData.setSubString(SubscriptionData.SUB_ALL);
} else {
// 分割 tags tagA || tagB
String[] tags = subString.split("\\|\\|");
if (tags.length > 0) {
for (String tag : tags) {
if (tag.length() > 0) {
String trimString = tag.trim();
if (trimString.length() > 0) {
subscriptionData.getTagsSet().add(trimString);
subscriptionData.getCodeSet().add(trimString.hashCode());
}
}
}
} else {
throw new Exception("subString split error");
}
}
return subscriptionData;
}
2.3 启动消费者
-
启动消费者首先调用
org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl#copySubscription:构建主题订阅信息 SubscriptionData 并加入到 rebalanceImpl 的订阅信息中。private void copySubscription() throws MQClientException { // 获取启动时设置的订阅信息 Map<String, String> sub = this.defaultMQPushConsumer.getSubscription(); if (sub != null) { for (final Map.Entry<String, String> entry : sub.entrySet()) { final String topic = entry.getKey(); final String subString = entry.getValue(); // 构建订阅信息 SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(this.defaultMQPushConsumer.getConsumerGroup(), topic, subString);<

最低0.47元/天 解锁文章
2979

被折叠的 条评论
为什么被折叠?



