分区顺序消息:
- 生产者 :需要确保消息按照某个特定的键(如订单 ID)发送到同一个队列。
- 消费者 :允许消费者使用多线程,但每个分区的消息必须由单个线程处理。
分区顺序消息生产者代码示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class OrderTestRunner implements CommandLineRunner {
@Autowired
private OrderProducer orderProducer;
@Override
public void run(String... args) throws Exception {
// 模拟发送多个订单消息
String orderId = "order-001";
orderProducer.sendSequentialMessage(orderId, "Step 1: Create Order");
orderProducer.sendSequentialMessage(orderId, "Step 2: Pay Order");
orderProducer.sendSequentialMessage(orderId, "Step 3: Deliver Order");
// 可以尝试发送另一个订单的消息
String anotherOrderId = "order-002";
orderProducer.sendSequentialMessage(anotherOrderId, "Step 1: Create Another Order");
orderProducer.sendSequentialMessage(anotherOrderId, "Step 2: Pay Another Order");
}
}
全局顺序消息:
- 生产者 :需要将所有消息发送到同一个队列。
- 消费者 :需要以单线程的方式消费该队列的消息。
全局顺序消息生产者代码示例:
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class GlobalOrderProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 发送消息到默认的第一个队列,并使用回调记录日志
*
* @param topic 主题名称
* @param messageBody 消息内容
*/
public void sendToFirstQueue(String topic, String messageBody) {
try {
// 创建消息对象
Message message = new Message(topic, null, null, messageBody.getBytes());
// 使用 MessageQueueSelector 选择第一个队列并发送消息
rocketMQTemplate.getProducer().send(
message,
(MessageQueueSelector) (mqs, msg, arg) -> {
if (mqs == null || mqs.isEmpty()) {
throw new IllegalStateException("No available queues for topic: " + topic);
}
// 始终选择第一个队列
return mqs.get(0);
},
null, // 无额外参数
new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
// 成功回调:记录日志
System.out.println("Message sent successfully: " + messageBody + ", Result: " + sendResult);
}
@Override
public void onException(Throwable throwable) {
// 异常回调:记录日志
System.err.println("Failed to send message: " + messageBody);
throwable.printStackTrace();
}
}
);
} catch (Exception e) {
// 异常处理
System.err.println("Error occurred while sending message: " + messageBody);
e.printStackTrace();
}
}
}
总结:
生产者:
- 分区顺序(局部顺序)消息生产, 每条消息必须指定一个键, 同一个键内的子消息保持顺序
- 全局顺序消息生产, 必须指定唯一的分区(
MessageQueue), 发送消息
生产者:
- 分区顺序消息消费, 可以多队列(
MessageQueue)消费, 单线程消费
- 全局顺序消息消费, 必须要保证单队列(
MessageQueue), 单线程消费