1.普通消息生命周期
(1)初始化:消息被生产者构建并完成初始化,待发送到服务端的状态。
(2)待消费:消息被发送到服务端,对消费者可见,等待消费者消费的状态。
(3)消费中:消息被消费者获取,并按照消费者本地的业务逻辑进行处理的过程。 此时服务端会等待消费者完成消费并提交消费结果,如果一定时间后没有收到消费者的响应,Apache RocketMQ会对消息进行重试处理。具体信息,请参见消费重试。
(4)消费提交:消费者完成消费处理,并向服务端提交消费结果,服务端标记当前消息已经被处理(包括消费成功和失败)。 Apache RocketMQ默认支持保留所有消息,此时消息数据并不会立即被删除,只是逻辑标记已消费。消息在保存时间到期或存储空间不足被删除前,消费者仍然可以回溯消息重新消费。
(5)消息删除:Apache RocketMQ按照消息保存机制滚动清理最早的消息数据,将消息从物理文件中删除。更多信息,请参见消息存储和清理机制。
2.以下条件之一可以触发发送重试:
(1)客户端调用失败或者请求超时。
网络异常导致连接失败或请求超时。
由于代理节点关闭或重新启动,连接被关闭。
由于代理运行缓慢,请求超时。
(2)代理返回错误代码。
逻辑错误:由于运行逻辑不正确而导致的错误。
限流:流量过大触发的限流。
您可以在生产者初始化消息时指定生产者的最大重试次数。当上述触发条件之一出现时,生产者客户端会尝试再次发送消息,直到消息发送完毕或达到最大重试次数。如果最后一次重试仍失败,则返回调用错误。
同步发送:调用线程被阻塞,直到重试成功或最后一次重试失败。如果最后一次重试失败,系统将返回错误代码和异常。
异步发送:调用线程不被阻塞。调用结果作为异常事件或成功事件返回。
3.重试
消息失败后会立即重试,除非通过限制触发重试。
如果通过限制触发重试,则会按照指数退避协议中指定的时间间隔重试消息。指数退避算法使用以下参数来控制重试行为:
INITIAL_BACKOFF:指定第一次失败和第一次重试之间的时间间隔。默认值:1 秒。
MULTIPLIER :指定每次重试失败后与间隔相乘的因子。默认值:1.6。
JITTER :指定随机间隔的因子。默认值:0.2。
MAX_BACKOFF:指定间隔的上限。默认值:120 秒。
MIN_CONNECT_TIMEOUT:指定最小间隔。默认值:20 秒。
当一条消息初次消费失败,消息队列 RocketMQ 会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列 RocketMQ 不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。
在消息队列 RocketMQ 中,这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。
死信特性
(1)不会再被消费者正常消费。
(2)有效期与正常消息相同,均为 3 天,3 天后会被自动删除。因此,请在死信消息产生后的 3 天内及时处理。(commitLog文件的过期时间)
死信队列具有以下特性:
(1)一个死信队列对应一个 Group ID, 而不是对应单个消费者实例。
如果一个 Group ID 未产生死信消息,消息队列 RocketMQ 不会为其创建相应的死信队列。
(2)一个死信队列包含了对应 Group ID 产生的所有死信消息,不论该消息属于哪个 Topic。
死信队列是一个特殊的Topic,名称为%DLQ%consumerGroup@consumerGroup
Producer参数
DefaultMQProducer defaultMQProducer = new DefaultMQProducer("test");
defaultMQProducer.setNamesrvAddr("192.168.233.1:9876");
defaultMQProducer.setProducerGroup("producer");
defaultMQProducer.setMaxMessageSize(1024*1024);
defaultMQProducer.setSendMsgTimeout(5000);
defaultMQProducer.setRetryTimesWhenSendFailed(3);
defaultMQProducer.setDefaultTopicQueueNums(3);
ExecutorService es = Executors.newFixedThreadPool(3);
defaultMQProducer.setAsyncSenderExecutor(es);
defaultMQProducer.setCallbackExecutor(es);
defaultMQProducer.setSendMessageWithVIPChannel(true);
defaultMQProducer.setRetryTimesWhenSendAsyncFailed(3000);
defaultMQProducer.setPersistConsumerOffsetInterval(3000);
consumer 参数
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test");
consumer.setAdjustThreadPoolNumsThreshold(3);
consumer.setMaxReconsumeTimes(-1);
consumer.setMessageModel(MessageModel.CLUSTERING);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.setNamesrvAddr("192.168.233.1:9876");
AllocateMessageQueueStrategy strategy = new AllocateMessageQueueAveragely();
consumer.setAllocateMessageQueueStrategy(strategy);
rocketmq 发送延迟消息
Message message = new Message(topic, JSON.toJSONBytes(order)); message.setDelayTimeLevel(3); //private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
rocketmq 发送顺序消息
Message message = new Message("topic-test", tags[i % tags.length], "KEY" + i, "HellowRocketMQ".getBytes());
SendResult sendResult = defaultMQProducer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer queue = (Integer) arg;
int index = queue % mqs.size();
return mqs.get(index);
}
}, orderId);
rocketmq 发送事务消息
DefaultMQProducer defaultMQProducer = new DefaultMQProducer("test"); defaultMQProducer.setTransactionListener(new LocalTransactionListener());defaultMQProducer.sendMessageInTransaction(message, null);
rocket mq核心配置
namesrvAddr=192.168.64.144:9876 #注册中心地址
brokerClusterName = DefaultCluster # 集群名称
brokerName = broker-c 节点名称
brokerId =2 # 大于0 为从节点
listenPort=10814 // 一台机器上启动多个broker 这个必须不同
deleteWhen = 04
fileReservedTime = 48 #本地文件保存多长时间,曾经面试问过
brokerRole = MASTER # 节点角色 是MASTER
flushDiskType = ASYNC_FLUSH
diskMaxUsedSpaceRatio=90 #磁盘实用多少报错
autoCreateTopicEnable = true #自动生成topic
brokerIP1=192.168.64.146 #本地网卡与外部连接的ip
brokerIP2=192.168.64.146 # 一般这个和第一个一样
storePathCommitLog=$ROCKETMQ_HOME/store/commitlog/ #数据文件存放地址
storePathConsumerQueue=$ROCKETMQ_HOME/store/consumequeue/
mappedFileSizeCommitLog=1024*1024*1024
enablePropertyFilter=true
orderMessageEnable=true
rocketmq 队列分配策略
rocketmq 注意事项
1.内存不足默认rocketmq 的启动内存是比较大的, 或者配置的时候-xmx -xms 一样大
也会有问题
cd $ROCKETMQ_HOME/bin.修改tools.sh runbroker.sh runserver.sh
2. rocketmq 配置一主多从的时候,使用java api 操作网卡会报错
3. rocketmq 的日志路径配置为 logback_broker.xml,logback_namesrv.xml.ogback_tools.xml
4. rocketmq 使用默人的send 不添加超时时间会超时,所以send 的时候加一个超时时间就不报错
例如这样 producer.send(message, 20000);
5. rocketmq 的事务消息实现TransactionListener 接口,在其中写查询本地业务逻辑接口。
6. 命令行查看集群信息
mqadmin topicList -b 192.168.64.144:10812 -n 192.168.64.144:9876
7.面试题
消息默认在4点被删除,消息保存时间默认2天,这个我已经吃过亏了,之前没注意这些配置。
deleteWhen = 04
fileReservedTime = 48
参考文件