DefaultMQPushConsumer,由系统控制拉取操作,即由我们项目中引入的rocketMQ框架主动的从Broker,将消息拉取到消费者本地。这个拉取动作对于我们程序员是无感的,当然我们也可以研究一下消费者项目中的引入的相关jar包,了解其实现原理。消费者收到消息后,rocket源码会自动调用传人的处理方法来处理消息。如下图红色部分
1.1 创建DefaultMQPushConsume消费者对象
// 指定组名
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name");
创建消费者对象的时候,一般会指定消费者组名groupName。下面是DefaultMQPushConsumer的各种配置属性。
1.1.1 groupName和messageModel属性
创建消费者对象的时候,一般会指定消费者组名。这个祖名groupName也就是订阅组。一般情况下,假如有多个消费者,每一个消费者都使用相同的groupName,那么这些消费者构成的就属于一个组也就是订阅组。Consumer的groupName用于把多个Consumer组织到一起,形成一个订阅组,这样订阅组里的每个消费者都会收到Topic里面的消息。订阅组里的每一个消费者如何接收topic的消息则有messageModel决定。
//set to broadcast mode
consumer.setMessageModel(MessageModel.BROADCASTING);
RocketMQ 支持两种消息模式: Clustering 和Broadcasting 。
- 在Clustering 模式下,同一个ConsumerGroup(GroupName相同)里的每个Consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer 消费的内容合起来才是所订阅Topic 内容的整体,从而达到负载均衡的目的。
- 在Broadcasting模式下,同一个ConsumerGroup里的每个Consumer都能消费到所订阅Topic的全部消息,也就是一个消息会被多次分发,被多个Consumer 消费。
1.1.2 consumerFromWhere属性
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
public enum ConsumeFromWhere {
// 一个新的订阅组第一次启动从队列的最后位置开始消费,后续再启动接着上次消费的进度开始消费
CONSUME_FROM_LAST_OFFSET,
/** @deprecated */
@Deprecated
CONSUME_FROM_LAST_OFFSET_AND_FROM_MIN_WHEN_BOOT_FIRST,
/** @deprecated */
@Deprecated
CONSUME_FROM_MIN_OFFSET,
/** @deprecated */
@Deprecated
CONSUME_FROM_MAX_OFFSET,
// 一个新的订阅组第一次启动从队列的最前位置开始消费,后续再启动接着上次消费的进度开始消费
CONSUME_FROM_FIRST_OFFSET,
// 一个新的订阅组第一次启动从指定时间点开始消费,后续再启动接着上次消费的进度开始消费
//时间点设置参照DefaultPushConsumer.consumeTimestamp参数
CONSUME_FROM_TIMESTAMP;
private ConsumeFromWhere() {
}
}
这个参数只对一个新的consumeGroup第一次启动时有效,就是说,如果是一个consumerGroup重启,他只会从自己上次消费到的offset,继续消费。这个参数是没用的。
1.1.3 topic和tag属性
consumer.subscribe("TopicTest", "Tag1 || Tag2 || Tag3");
Topic名称用来标识消息类型,需要提前创建。如果不需要消费某个Topic 下的所有消息,可以通过指定消息的Tag 进行消息过滤,比如:consumer.subscribe(”Topic Test”J ’tagl 11 tag2 11 tag3 ”),表示这个consumer 要消费“ TopicTest ”下带有tagl 或tag2 或tag3 的消息( Tag 是在发送消息时设置的标签)。在填写Tag 参数的位置,用null 或者“*” 表示要消费这个Topic的所有消息。
1.1.4 consumerThreadMin和consumerThreadMax属性
消费者使用一个 ThreadPoolExecutor 来处理内部的消费,因此您可以通过设置setConsumeThreadMin或setConsumeThreadMax来更改它,它的默认值为20。这个属性能够增加消费者服务器的处理线程数,提高消费速度。
public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsumer {
private final InternalLogger log = ClientLogger.getLog();
//......
/**
* Minimum consumer thread number
*/
private int consumeThreadMin = 20;
/**
* Max consumer thread number
*/
private int consumeThreadMax = 20;
public int getConsumeThreadMax() {
return consumeThreadMax;
}
public int getConsumeThreadMin() {
return consumeThreadMin;
}
//......
}
public class ConsumeMessageConcurrentlyService implements ConsumeMessageService {
private static final InternalLogger log = ClientLogger.getLog();
private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl;
private final DefaultMQPushConsumer defaultMQPushConsumer;
private final MessageListenerConcurrently messageListener;
private final BlockingQueue<Runnable> consumeRequestQueue;
private final ThreadPoolExecutor consumeExecutor;
private final String consumerGroup;
private final ScheduledExecutorService scheduledExecutorService;
private final ScheduledExecutorService cleanExpireMsgExecutors;
public ConsumeMessageConcurrentlyService(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl,
MessageListenerConcurrently messageListener) {
this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl;
this.messageListener = messageListener;
this.defaultMQPushConsumer = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer();
this.consumerGroup = this.defaultMQPushConsumer.getConsumerGroup();
this.consumeRequestQueue = new LinkedBlockingQueue<Runnable>();
// 创建线程池用来处理消息,consumeThreadMin、consumeThreadMax分别作为核心线程数和最大线程数
this.consumeExecutor = new ThreadPoolExecutor(
this.defaultMQPushConsumer.getConsumeThreadMin(),
this.defaultMQPushConsumer.getConsumeThreadMax(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.consumeRequestQueue,
new ThreadFactoryImpl("ConsumeMessageThread_"));
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("ConsumeMessageScheduledThread_"));
this.cleanExpireMsgExecutors = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("CleanExpireMsgScheduledThread_"));
}
//......
}
1.1.5 pullBatchSize和consumeMessageBatchMaxSize属性
pullBatchSize是consumer每次从broker拉取的消息最大数,拉取后新消息先存储到consumer内存中。而consumeMessageBatchMaxSize参数代表了,每次将内存中存储的新消息(pullBatchSize参数拉取的消息)传递给开发者自定义的处理方法的最多条数,也是为了提高消费速度的配置项。
consumer.setPullBatchSize(100);
consumer.setConsumeMessageBatchMaxSize(10);
consumer.registerMessageListener(new MessageListenerConcurrently() {
// 使用list的方法
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for(MessageExt msg : msgs) {
System.out.println("-------->" + msg.getKeys());
System.out.println("-------->" + msg.getMsgId());
System.out.println("-------->" + msg.getQueueId());
System.out.println("-------->" + msg.getQueueOffset());
System.out.println("-------->" + msg.getBody().toString());
System.out.println("-------->" + msg.toString());
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
1.1.6 instanceName属性
假如一个项目里面需要连接2个RocketMQ集群,则单个MQClientInstance无法支持这种场景,一定要手动指定InstanceName,这时底层会创建两个MQClientInstance对象。
consumer.setInstanceName()