RocketMQ-消息拉取Pull

一、问题思考

消息拉取在实践过程中,有以下几个问题需要考虑:

1、如何全量拉取消息?

2、如何指定MessageQueue从指定offset处拉取消息?

3、如何更新MessageQueue的Offset标志位?

4、Pull模式下如何实现负载均衡?

二、Pull模式下常用Demo

1、更新MessageQueue的Offset标志位

consumer.updateConsumeOffset(mq, pullResult.getNextBeginOffset());

2、Pull模式简单Demo

public static void main(String[] args) throws MQClientException {
		DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("PullConsumer");
		consumer.setNamesrvAddr("10.72.86.241:9876;10.72.86.229:9876");

		consumer.start();
		
		// 从指定topic中拉取所有消息队列
		Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("user-info");
		
		for (MessageQueue mq : mqs) {
			// 获取消息的offset,指定从store中获取
			long offset = consumer.fetchConsumeOffset(mq, true);
			System.out.println("consumer from the queue:" + mq + ":" + offset);
			
			try {
				while (true) {
					PullResult pullResult = consumer.pullBlockIfNotFound(mq,
							null, consumer.fetchConsumeOffset(mq, false), 1);
					
					consumer.updateConsumeOffset(mq, pullResult.getNextBeginOffset());

					switch (pullResult.getPullStatus()) {
					case FOUND:
						List<MessageExt> messageExtList = pullResult.getMsgFoundList();
						for (MessageExt m : messageExtList) {
							System.out.println(m.toString());
						}
						break;
					case NO_MATCHED_MSG:
						break;
					case NO_NEW_MSG:
						break;
					case OFFSET_ILLEGAL:
						break;
					default:
						break;
					}
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		consumer.shutdown();
	}

3、指定MessageQueue拉取消息

public class PullMQConsumerMain {
	public static void main(String[] args) throws MQClientException {
		DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("PullConsumer");
		consumer.setNamesrvAddr("10.72.86.241:9876;10.72.86.229:9876");

		consumer.start();
		
		try {
			//从指定topic的MessageQueue中拉取消息
			MessageQueue mq = new MessageQueue();
			mq.setQueueId(0);
			mq.setTopic("user-info");
			mq.setBrokerName("broker-a");
			//指定获取消息的offset
			long offset = 26;
			
			PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, offset, 32);
			//更新offset
			consumer.updateConsumeOffset(mq, pullResult.getNextBeginOffset());
			
			System.out.println("最新 offset :" + consumer.fetchConsumeOffset(mq, false));

			switch (pullResult.getPullStatus()) {
			case FOUND:
				List<MessageExt> messageExtList = pullResult
						.getMsgFoundList();
				for (MessageExt m : messageExtList) {
					System.out.println(m.toString());
				}
				break;
			case NO_MATCHED_MSG:
				break;
			case NO_NEW_MSG:
				break;
			case OFFSET_ILLEGAL:
				break;
			default:
				break;
			}
        } catch (Exception e) {
            e.printStackTrace();
        }

        consumer.shutdown();
	}
}

4、Pull模式下负载均衡(MQPullConsumerScheduleService)

public class PullScheduleMain {
	public static void main(String[] args) throws MQClientException {
		final MQPullConsumerScheduleService scheduleService = new MQPullConsumerScheduleService("PullSchedule");
		scheduleService.getDefaultMQPullConsumer().setNamesrvAddr("10.72.86.241:9876;10.72.86.229:9876");
		scheduleService.setMessageModel(MessageModel.CLUSTERING);
		
		scheduleService.registerPullTaskCallback("user-info", new PullTaskCallback() {
			
			@Override
			public void doPullTask(MessageQueue mq, PullTaskContext context) {
				// TODO Auto-generated method stub
				MQPullConsumer consumer = context.getPullConsumer();
				
				try {
					long offset = consumer.fetchConsumeOffset(mq, false);
					if(offset < 0)
						offset = 0;
					
					PullResult pullResult = consumer.pullBlockIfNotFound(mq, null, offset, 4);

					switch (pullResult.getPullStatus()) {
					case FOUND:
						List<MessageExt> messageExtList = pullResult
								.getMsgFoundList();
						for (MessageExt m : messageExtList) {
							System.out.println(m.toString());
						}
						break;
					case NO_MATCHED_MSG:
						break;
					case NO_NEW_MSG:
						break;
					case OFFSET_ILLEGAL:
						break;
					default:
						break;
					}
					
					consumer.updateConsumeOffset(mq, pullResult.getNextBeginOffset());
					context.setPullNextDelayTimeMillis(10000);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
		
		scheduleService.start();
	}
}

三、总结

      分别用四个例子回答了上面的4个问题,后续会通过源码解析的方式描述Pull模式的实现机制。

      遗留问题:

      调用fetchMessageQueuesInBalance函数时,返回MessageQueue为空

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值