Rocket消息的顺序消费是局部的顺序消费
举个例子:
同一笔订单,需要按照顺序处理 1.下单 2.支付 3.发货 4.确认收货 5.评价
但是不同的订单,则不需要按照顺序处理,不需要第一笔订单评价完成,才能处理第二笔订单的下单
有两点
- 一个MQ节点一般有4个队列,生产者需要将同一个订单发送到的所有信息 (下单、支付、发货、确认收货、评价)放到一个队列中
- 消费者在消费消息的时候,只能有一个线程来处理一个消息队列,4个队列就创建4个线程来处理。
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.util.List;
/**
* 发送顺序消息
*/
public class OrderProducer {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException {
DefaultMQProducer producer = new DefaultMQProducer("orderGroup");
producer.setNamesrvAddr("192.168.197.126:9876;192.168.197.123:9876");
producer.start();
List<Order> orders = OrderBuilder.buildOrder();
for(Order order:orders){
Message message = new Message("OrderTopic","tag",order.toString().getBytes());
//发送消息的时候,传递一个MessageQueueSelector类型对象,
SendResult sendResult = producer.send(message, (list, message1, args1) -> {
//获取到订单ID
long orderId = (long) args1;
//获取MQ的队列数量
long index = orderId % list.size();
//根据ID取模,这样订单ID相同的消息,都会被放到同一个队列中去
return list.get((int)index);
}, order.getId());
System.out.println(sendResult);
}
producer.shutdown();
}
}
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.common.message.MessageExt;
/**
* 顺序消费消息
*/
public class Consumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("orderGroup");
consumer.setNamesrvAddr("192.168.197.126:9876;192.168.197.123:9876");
consumer.subscribe("OrderTopic","*");
//这里的消息监听器,必须是MessageListenerOrderly
consumer.registerMessageListener((MessageListenerOrderly) (list, consumeOrderlyContext) -> {
for (MessageExt messageExt : list) {
String tName = Thread.currentThread().getName();
System.out.println("收到消息-"+tName+"-"+new String(messageExt.getBody()));
}
return ConsumeOrderlyStatus.SUCCESS;
});
consumer.start();
System.out.println("consumer启动成功");
}
}