RocketMQ(5)- RockerMQ 消息消费

1 消费模式

1.1 Pull 模式

  1. 自主选择 Message Queueoffset 进行消息拉取,用户拉取消息时,需要用户自己来决定拉去哪个队列从哪个offset开始,拉取多少消息。
  2. 用户自己维护 offsetStore ,具体的消费进度 roccketMQ 不会进行存储,用户可以存入 redis 或者调用 MQ 接口保存。
  3. 用户大都采用 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;
}
  1. 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 启动消费者

  1. 启动消费者首先调用 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);<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值