RocketMQ由producer、NameServer、broker、consumer组成
Producer:
为生产者,消息的来源。需要与NameServer建立连接,从NameServer获取Topic对应的Message Queue的broker地址
NameServer:
相当于一个路由器,存着broker的地址信息和对应的topic信息。NameServer可以横向扩展,broker和每一台NameServer建立长连接
Broker:
Broker是RocketMQ的核心,提供了消息的接收,存储,拉取等功能。Broker可以配置主从,主从关系通过BrokerId来定义,0为主1为从。
Consumer
消费者,同样与NameServer建立连接,从NameServer获取Topic对应的Message Queue的broker地址。然后与Broker Master、Slave建立连接。
topic与message queue
发送消息时,需要指定msg的topic,每个topic可以设置多个queue,默认为4个
不同的topic对应的queue不同。
准备工作
安装RocketMQ,并启动NameServer和Broker,因为broker启动时要在Nameserver注册信息,所以要先启动NameServer再启动Broker
发送消息
消息发送使用Producer的send方法来发送消息。
DefaultMQProducer为rmq的默认producer类,我们创建DefaultMQProducer对象作为producer来发送消息,创建DefaultMQProducer对象时需要传入NameServer地址和producerGroup名字,其他参数可不填(有默认配置)
DefaultMQProducer producer = new DefaultMQProducer("group1");
producer.setNamesrvAddr("106.53.xx.xxx:9876");
发送的消息为Message格式,里面有我们所要发送的信息body,消息绑定的tags和消息绑定的topic
topic可以在发送消息前创建,如果不主动创建,在发送消息的时候会自动创建
public Message(String topic, String tags, byte[] body) {
this(topic, tags, "", 0, body, true);
}
producer发送消息有三种基本方式
- 同步
2 . 异步
- 单向
/**
* 同步发送
* 需要返回结果
*/
public SendResult sendNeedResult() throws InterruptedException, MQClientException, MQBrokerException {
SendResult sendResult = producer.send(message);
}
/**
* 异步发送
* 回调方法中返回结果
*/
public void sendNeedResultByCallBack() throws MQClientException, InterruptedException {
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
//成功的处理
}
@Override
public void onException(Throwable e) {
//失败的处理
}
});
}
/**
* 单向发送
* 无需返回结果
*/
public void sendNotNeedResul() throws MQClientException, InterruptedException {
producer.sendOneway(message);
}
消费消息
Consumer的基本的默认实现有两种DefaultMQPushConsumer、DefaultMQPullConsumer;push的底层也是pull。这里只介绍push
DefaultMQPushConsumer consumer =
new DefaultMQPushConsumer("group1");
consumer.setNamesrvAddr("106.xx.xx.xxx:9876");
consumer.subscribe("OrderTopic","*");
//非强制配置,默认为集群
consumer.setMessageModel(MessageModel.CLUSTERING);
//非强制配置,默认为CONSUME_FROM_FIRST_OFFSET
consumer.setConsumeFromWhere();
使用consumer前需要设定nameserver地址、订阅主题、设置所在组名
CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费
CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费
CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费
以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始
广播消费、集群消费
BROADCASTING广播模式,CLUSTERING集群模式,默认的是 集群消费模式。
广播消费指的是:一条消息被多个consumer消费,即使这些consumer属于同一个ConsumerGroup,消息也会被ConsumerGroup中的每个Consumer都消费一次。
集群消费模式:一个ConsumerGroup中的Consumer实例平均分摊消费消息。例如某个Topic有9条消息,其中一个ConsumerGroup有3个实例(可能是3个进程,或者3台机器),那么每个实例只消费其中部分,消费完的消息不能被其他实例消费。
集群消费下的负载均衡
一旦有新的consumer连接到broker,broker会进行一次负载均衡,以queue为最小单位,订阅的所有queue分配给不同的consumer消费。任何时候一个队列只对应一个consumer
AllocateMessageQueueStrategy allocateMessageQueueStrategy
消息分配策略,用于集群模式下,消息平均分配给所有客户端
默认实现为AllocateMessageQueueAveragely
消息监听器、消费方式
监听器监听消息,收到消息后,就执行监听器的方法执行具体消费。
监听器分为两种:(并发消费)ConsumeMessageConcurrentlyService,(顺序消费)为ConsumeMessageOrderlyService
消费失败问题
并发消费返回的状态有两种:
ConsumeConcurrentlyStatus.RECONSUME_LATER、
ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
前者为消费失败稍后重试,后者为消费成功
若消费失败(抛出异常或者返回了失败)。为了保证消息是肯定被至少消费成功一次,RocketMQ会把这批消息重发回Broker(topic不是原topic而是这个消费租的RETRY topic),在延迟的某个时间点(默认是10秒,业务可设置)后,再次投递到这个ConsumerGroup。而如果一直这样重复消费都持续失败到一定次数(默认16次),就会投递到DLQ死信队列。应用可以监控死信队列来做人工干预。
顺序消费返回的状态有两种:
ConsumeOrderlyStatus.SUCCESS
SUSPEND_CURRENT_QUEUE_A_MOMENT
前者为消费成功,后者为消费失败
由于顺序消费是要前者消费成功才能继续消费,所以没有RECONSUME_LATER的这个状态,只有SUSPEND_CURRENT_QUEUE_A_MOMENT来暂停队列的其余消费,直到原消息不断重试成功为止才能继续消费。
顺序消费消费失败后,不会把该消息放入重试队列,而是保留在当前队列继续重试消费直到成功,才继续往下消费。所以顺序消费可能出现某个队列被卡住的现象。
顺序消费问题:
不管是顺序消费还是并发消费,comsumer会同时消费拥有的所有queue,而不是消费完queue1再去消费queue2,所以不同queue中消息的顺序性消费不能保证;
queue内的顺序:由于顺序消费是要前者消费成功才能继续消费所以顺序消费的queue内部的消费是有序的。
默认线程数
默认list中消息数
ConsumeFromWhere是干嘛的
MessageModel是干嘛的
send消息的整个流程
消费失败处理策略
是如何push和pull的
查看队列中的消息是否堆积或者消息剩余情况
顺序消费时的context.setAutoCommit(true);有什么含义
ClientConfig#clientCallbackExecutorThreads
consumer默认的线程池
RPCHook是什么
负载均衡