RocketMQ基本使用与编程实践

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.7k人参与

RocketMQ基本使用与编程实践

Maven依赖配置

在开始编写RocketMQ应用程序之前,需要在项目的pom.xml文件中添加RocketMQ客户端依赖:

<dependencies>
    <!-- RocketMQ客户端依赖 -->
    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-client</artifactId>
        <version>5.1.4</version>
    </dependency>
    
    <!-- RocketMQ工具依赖(可选) -->
    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-tools</artifactId>
        <version>5.1.4</version>
    </dependency>
</dependencies>

消息生产者(Producer)

1. 基本消息发送

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.common.RemotingHelper;

public class SyncProducer {
    public static void main(String[] args) throws Exception {
        // 创建Producer实例,指定生产者组名
        DefaultMQProducer producer = new DefaultMQProducer("producer_group_name");
        
        // 设置NameServer地址
        producer.setNamesrvAddr("localhost:9876");
        
        // 启动Producer实例
        producer.start();
        
        for (int i = 0; i < 10; i++) {
            // 创建消息对象,指定Topic、Tag和消息体
            Message msg = new Message("TopicTest" /* Topic */,
                    "TagA" /* Tag */,
                    ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
            );
            
            // 发送消息并等待结果
            SendResult sendResult = producer.send(msg);
            System.out.printf("%s%n", sendResult);
        }
        
        // 关闭Producer实例
        producer.shutdown();
    }
}

2. 异步消息发送

import org.apache.rocketmq.client.producer.DefaultMQProducer;
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.remoting.common.RemotingHelper;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class AsyncProducer {
    public static void main(String[] args) throws Exception {
        // 创建Producer实例
        DefaultMQProducer producer = new DefaultMQProducer("async_producer_group");
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        
        // 设置发送失败时的重试次数
        producer.setRetryTimesWhenSendAsyncFailed(0);
        
        int messageCount = 10;
        final CountDownLatch countDownLatch = new CountDownLatch(messageCount);
        
        for (int i = 0; i < messageCount; i++) {
            try {
                final int index = i;
                Message msg = new Message("TopicTest",
                        "TagB",
                        "OrderID188",
                        ("Hello world" + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                
                // 异步发送消息
                producer.send(msg, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.printf("%-10d OK %s %n", index,
                                sendResult.getMsgId());
                        countDownLatch.countDown();
                    }
                    
                    @Override
                    public void onException(Throwable e) {
                        System.out.printf("%-10d Exception %s %n", index, e);
                        e.printStackTrace();
                        countDownLatch.countDown();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        // 等待所有异步消息发送完成
        countDownLatch.await(5, TimeUnit.SECONDS);
        producer.shutdown();
    }
}

3. 单向消息发送

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

public class OnewayProducer {
    public static void main(String[] args) throws Exception {
        // 创建Producer实例
        DefaultMQProducer producer = new DefaultMQProducer("oneway_producer_group");
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        
        for (int i = 0; i < 10; i++) {
            Message msg = new Message("TopicTest",
                    "TagC",
                    ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
            
            // 单向发送消息,不等待响应
            producer.sendOneway(msg);
        }
        
        // 等待5秒以确保消息发送完成
        Thread.sleep(5000);
        producer.shutdown();
    }
}

消息消费者(Consumer)

1. 推模式消费者(Push Consumer)

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class PushConsumer {
    public static void main(String[] args) throws Exception {
        // 创建Consumer实例,指定消费者组名
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_group_name");
        
        // 设置NameServer地址
        consumer.setNamesrvAddr("localhost:9876");
        
        // 订阅Topic和Tag
        consumer.subscribe("TopicTest", "*");
        
        // 注册消息监听器
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                            ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                
                // 返回消费状态
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        
        // 启动Consumer实例
        consumer.start();
        System.out.printf("Consumer Started.%n");
        
        // 保持程序运行
        System.in.read();
    }
}

2. 拉模式消费者(Pull Consumer)

import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.common.message.MessageQueue;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class PullConsumer {
    private static final Map<MessageQueue, Long> offseTable = new HashMap<>();
    
    public static void main(String[] args) throws Exception {
        // 创建PullConsumer实例
        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("pull_consumer_group");
        consumer.setNamesrvAddr("localhost:9876");
        consumer.start();
        
        // 获取指定Topic的所有消息队列
        Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("TopicTest");
        
        for (MessageQueue mq : mqs) {
            System.out.printf("Consume from the queue: %s%n", mq);
            
            SINGLE_MQ:
            while (true) {
                try {
                    // 拉取消息
                    PullResult pullResult =
                            consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                    System.out.printf("%s%n", pullResult);
                    
                    // 更新消费位置
                    putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                    
                    switch (pullResult.getPullStatus()) {
                        case FOUND:
                            // 处理消息
                            dealWithPullResult(pullResult);
                            break;
                        case NO_MATCHED_MSG:
                            break;
                        case NO_NEW_MSG:
                            break SINGLE_MQ;
                        case OFFSET_ILLEGAL:
                            break;
                        default:
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        consumer.shutdown();
    }
    
    private static long getMessageQueueOffset(MessageQueue mq) {
        Long offset = offseTable.get(mq);
        if (offset != null)
            return offset;
        
        return 0;
    }
    
    private static void putMessageQueueOffset(MessageQueue mq, long offset) {
        offseTable.put(mq, offset);
    }
    
    private static void dealWithPullResult(PullResult pullResult) {
        if (pullResult.getMsgFoundList() != null) {
            for (MessageExt msg : pullResult.getMsgFoundList()) {
                System.out.printf("Received message: %s%n", new String(msg.getBody()));
            }
        }
    }
}

消息类型详解

1. 普通消息

普通消息是最基本的消息类型,适用于大多数业务场景。

Message msg = new Message("TopicTest", 
                         "TagA", 
                         "KEY123", 
                         "Hello RocketMQ".getBytes());

2. 顺序消息

顺序消息保证消息按照发送顺序被消费。

// 生产者端
public class OrderlyProducer {
    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer = new DefaultMQProducer("orderly_producer_group");
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        
        String[] tags = new String[]{"TagA", "TagB", "TagC"};
        
        for (int i = 0; i < 10; i++) {
            int orderId = i % 3;
            Message msg = new Message("OrderTopic", tags[orderId], 
                                    "KEY" + orderId,
                                    ("Hello RocketMQ " + i).getBytes());
            
            // 发送顺序消息,使用orderId作为选择队列的参数
            SendResult sendResult = producer.send(msg, (mqs, msg1, arg) -> {
                Integer id = (Integer) arg;
                int index = id % mqs.size();
                return mqs.get(index);
            }, orderId);
            
            System.out.printf("%s%n", sendResult);
        }
        
        producer.shutdown();
    }
}

// 消费者端
public class OrderlyConsumer {
    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("orderly_consumer_group");
        consumer.setNamesrvAddr("localhost:9876");
        consumer.subscribe("OrderTopic", "*");
        
        // 注册顺序消息监听器
        consumer.registerMessageListener((MessageListenerOrderly) (msgs, context) -> {
            for (MessageExt msg : msgs) {
                System.out.printf("Receive message: %s%n", new String(msg.getBody()));
            }
            return ConsumeOrderlyStatus.SUCCESS;
        });
        
        consumer.start();
        System.out.printf("Orderly Consumer Started.%n");
        System.in.read();
    }
}

3. 广播消息

广播消息会发送给同一消费者组内的所有消费者。

// 设置消费模式为广播模式
consumer.setMessageModel(MessageModel.BROADCASTING);

消息属性设置

Message msg = new Message("TopicTest", 
                         "TagA", 
                         "KEY123", 
                         "Hello RocketMQ".getBytes());

// 设置延迟级别(1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h)
msg.setDelayTimeLevel(3); // 延迟10秒

// 设置自定义属性
msg.putUserProperty("property1", "value1");
msg.putUserProperty("property2", "value2");

// 设置消息键
msg.setKeys("KEY123");

小结

本章介绍了RocketMQ的基本使用方法,包括消息生产者和消费者的编程实践。我们学习了三种消息发送方式(同步、异步、单向)和两种消费模式(推模式、拉模式),以及顺序消息和广播消息的使用方法。

掌握了这些基础知识后,在下一章节中,我们将深入学习RocketMQ的高级特性,如事务消息、定时消息等。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员码小跳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值