准备工作
先用命令创建Topic,执行成功后默认会创建8个队列
sh mqadmin updateTopic -b localhost:10911 -n localhost:9876 -t TopicTest
Producer发送消息时,Topic不存在也会自动创建,但是一般不建议这样做。
同步生产
发送消息时,等待返回结果才发送下一条。速度相对慢一点,消息不易丢失。
public class SyncProducer {
public static void main(String[] args) throws Exception {
final String producerGroup = "default_producer";
final String topic = "TopicTest";
//实例化消息生产者Producer
DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
//设置NameServer的地址
producer.setNamesrvAddr("192.168.25.131:9876");
//启动Producer实例
producer.start();
for (int i = 0; i < 20; i++) {
//创建消息,并指定Topic,Tag和消息体
byte[] body = ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET);
Message message = new Message(topic, "TagA", body);
//发送消息(同步)
SendResult result = producer.send(message);
System.out.println(result);
}
//关闭
producer.shutdown();
}
}
异步生产
发送消息时,RocketMQ底层会调用线程池进行异步发送。延迟低,速度快,存在消息丢失的可能。
public class AsyncProducer {
public static void main(String[] args) throws Exception {
final String producerGroup = "default_producer";
final String topic = "TopicTest";
//实例化消息生产者Producer
DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
//设置NameServer的地址
producer.setNamesrvAddr("192.168.25.131:9876");
//启动Producer实例
producer.start();
for (int i = 0; i < 10; i++) {
//创建消息,并指定Topic,Tag和消息体
byte[] body = ("async message-" + i).getBytes(RemotingHelper.DEFAULT_CHARSET);
Message message = new Message(topic, "TagA", body);
//发送消息
producer.send(message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("异步发送:" + sendResult);
}
@Override
public void onException(Throwable throwable) {
throwable.printStackTrace();
}
});
}
//由于是异步方式,这里先等待一段时间,再关闭producer。避免出现消息未全部发送,就已经关闭了
Thread.sleep(5000);
producer.shutdown();
}
}
有序消费
前面的文章提过:一个Topic可能会存在多个消息队列。
有序消费的意思,就是保证相同队列的消息是顺序消费的,先进先出;但是不保证全局的有序。
public class OrderlyConsumer {
public static void main(String[] args) throws Exception {
final String consumerGroup = "default_consumer";
final String topic = "TopicTest";
//实例化消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
//设置NameServer的地址
consumer.setNamesrvAddr("192.168.25.131:9876");
//订阅一个或者多个Topic,以及Tag来过滤需要消费的消息
consumer.subscribe(topic, "*");
//注册回调实现类来处理从broker拉取回来的消息
consumer.registerMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
for (MessageExt msgExt : list) {
byte[] body = msgExt.getBody();
System.out.println(Thread.currentThread().getName() + ":" + new String(body));
}
// 标记该消息已经被成功消费
return ConsumeOrderlyStatus.SUCCESS;
}
});
// 启动消费者实例
consumer.start();
System.out.printf("启动成功");
}
}
并发消费
保证相同队列的消息是并发消费的,不保证任何顺序性,性能最快
public class ConcurrentlyConsumer {
public static void main(String[] args) throws Exception {
final String consumerGroup = "default_consumer";
final String topic = "TopicTest";
//实例化消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
//设置NameServer的地址
consumer.setNamesrvAddr("192.168.25.131:9876");
//订阅一个或者多个Topic,以及Tag来过滤需要消费的消息
consumer.subscribe(topic, "*");
//注册回调实现类来处理从broker拉取回来的消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt ext : list) {
System.out.println(Thread.currentThread().getName() + "," + ext.getQueueId() + "," + new String(ext.getBody()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 启动消费者实例
consumer.start();
System.out.printf("Consumer Started");
}
}