概述
本文详细介绍了RocketMQ的环境搭建、消息发送与接收的基础知识,同时提供了丰富的代码示例和实际应用案例,旨在帮助读者深入理解RocketMQ的工作原理和使用方法。手写RocketMQ资料涵盖了从基础概念到高级功能的全面解析,帮助开发者快速上手并优化RocketMQ的使用体验。
RocketMQ简介与环境搭建RocketMQ是什么
RocketMQ是一款由阿里巴巴开源的分布式消息中间件,主要提供高吞吐量、高可用性的消息传输服务。它基于轻量级的消息模型,实现了跨数据中心的可靠性传输与流量削峰。RocketMQ运用了高可用、高性能的设计理念,具有丰富的消息路由、过滤、消息堆积等特性,适用于多种分布式应用场景。
环境准备与安装
系统需求
- 操作系统:支持Linux、Windows
- Java环境:JDK 1.8及以上版本
- Maven:用于构建RocketMQ项目
安装步骤
- 下载RocketMQ源码包,使用Git或其他方式从GitHub上获取代码。
- 解压源码包,使用Maven工具进行编译,生成RocketMQ的可执行文件。
git clone https://github.com/apache/rocketmq.git
cd rocketmq
mvn clean install -DskipTests
- 启动RocketMQ服务,进入RocketMQ解压后的bin目录,分别运行以下命令启动名为server的日志服务和namesrv服务。
nohup sh bin/mqnamesrv &
nohup sh bin/mqbroker -n 127.0.0.1:9876 &
验证安装
运行以下Python脚本,检查RocketMQ是否正常启动。
import subprocess
def check_server():
process = subprocess.Popen(['ps', '-ef'], stdout=subprocess.PIPE)
output, error = process.communicate()
if error:
print("Error occurred while checking RocketMQ server: ", error)
else:
stdout = output.decode('utf-8')
if "org.apache.rocketmq.namesrv.NamesrvStartup" in stdout:
print("RocketMQ nameserver is running.")
if "org.apache.rocketmq.broker.BrokerRun" in stdout:
print("RocketMQ broker is running.")
else:
print("RocketMQ server is not running.")
check_server()
配置文件示例
配置文件conf/broker.properties
中包含一些重要的配置选项,如Broker的IP地址、端口号等。以下是一些基本配置示例:
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
brokerRole=ASYNC_MASTER
listenPort=10911
namesrvAddr=127.0.0.1:9876
快速开始指南
以下是一个快速入门示例,展示如何使用RocketMQ发送和接收消息。
发送消息示例
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 Producer {
public static void main(String[] args) throws Exception {
// 创建生产者,设置生产者组名
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
// 设置NameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
// 启动生产者
producer.start();
// 创建消息
Message msg = new Message("TestTopic", // topic
"TagA", // tag
"OrderID188", // key
("Hello RocketMQ.").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
// 发送消息
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
// 关闭生产者
producer.shutdown();
}
}
接收消息示例
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import java.util.List;
public class Consumer {
public static void main(String[] args) throws Exception {
// 创建消费者,设置消费者组名
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
// 设置NameServer地址
consumer.setNamesrvAddr("127.0.0.1:9876");
// 订阅主题和tag
consumer.subscribe("TestTopic", "TagA");
// 设置从何处消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
// 注册消息监听器
consumer.registerMessageListener((List<MessageExt> msgs, ConsumeOrderlyContext context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s%n", new String(msg.getBody()));
}
return ConsumeOrderlyStatus.SUCCESS;
});
// 启动消费者
consumer.start();
System.out.println("Consumer started.");
}
}
消息发送与接收基础
发送消息的步骤详解
消息发送的过程包括创建生产者实例、设置生产者组名、设置NameServer地址、启动生产者、创建消息、发送消息、关闭生产者。下面逐个步骤进行说明。
- 创建生产者实例
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
- 设置NameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
- 启动生产者
producer.start();
- 创建消息
Message msg = new Message("TestTopic", // topic "TagA", // tag "OrderID188", // key ("Hello RocketMQ.").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
- 发送消息
SendResult sendResult = producer.send(msg);
- 关闭生产者
producer.shutdown();
接收消息的实践操作
消息接收主要是通过创建消费者实例、设置消费者组名、订阅主题和tag、注册消息监听器、启动消费者来实现。以下是详细的步骤说明。
- 创建消费者实例
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
- 设置NameServer地址
consumer.setNamesrvAddr("127.0.0.1:9876");
- 订阅主题和tag
consumer.subscribe("TestTopic", "TagA");
- 注册消息监听器
consumer.registerMessageListener((List<MessageExt> msgs, ConsumeOrderlyContext context) -> { for (MessageExt msg : msgs) { System.out.printf("Received message: %s%n", new String(msg.getBody())); } return ConsumeOrderlyStatus.SUCCESS; });
- 启动消费者
consumer.start();
消息发送与接收的注意事项
- 发送消息时需要设置生产者组名和NameServer地址,确保这些配置正确。
- 消息的topic和tag必须与接收方一致,否则接收方无法接收到消息。
- 发送方和接收方需要保持网络连接稳定,避免网络故障导致的消息丢失。
- 消息发送频繁时,考虑使用批量发送以提高性能。
- 消息消费时可能出现重复消费,需要保证业务逻辑的幂等性。
消息过滤示例
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.common.message.MessageExt;
import java.util.List;
public class ConsumerWithFilter {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TestTopic", "*");
consumer.registerMessageListener((List<MessageExt> msgs, ConsumeOrderlyContext context) -> {
for (MessageExt msg : msgs) {
String tag = msg.getTopic() + ":" + msg.getTag();
if (tag.equals("TestTopic:TagA")) {
System.out.printf("Received message: %s%n", new String(msg.getBody()));
} else {
System.out.println("Message filtered out.");
}
}
return ConsumeOrderlyStatus.SUCCESS;
});
consumer.start();
System.out.println("Consumer started with message filtering.");
}
}
批量发送消息示例
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class ProducerWithBatch {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message[] msgs = new Message[10];
for (int i = 0; i < 10; i++) {
msgs[i] = new Message("TestTopic", // topic
"TagA", // tag
"OrderID" + i, // key
("Hello RocketMQ batch " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
}
SendResult sendResult = producer.send(msgs);
System.out.printf("SendResult: %s%n", sendResult);
producer.shutdown();
}
}
实际案例分析与应用
实际项目中的应用案例分析
假设有一个电商网站,需要处理大量订单请求。使用RocketMQ可以实现订单请求的异步处理,提高系统性能。
- 订单生成
- 用户下单后,订单信息通过RocketMQ异步发送到订单服务。
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 OrderProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("OrderProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("OrderTopic", // topic
"OrderTag", // tag
"OrderID123", // key
("Order information").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
SendResult sendResult = producer.send(msg);
System.out.printf("Order sent: %s%n", sendResult);
producer.shutdown();
}
}
- 库存减少
- 订单服务接收到订单信息,同步库存服务减少相应库存。
public class InventoryService {
public void decreaseInventory(String orderId) {
// 逻辑处理代码
System.out.println("Inventory decreased for order: " + orderId);
}
}
- 支付确认
- 订单服务基于RocketMQ通知支付系统进行支付确认。
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 PaymentProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("PaymentProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("PaymentTopic", // topic
"PaymentTag", // tag
"OrderID123", // key
("Payment confirmation").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
SendResult sendResult = producer.send(msg);
System.out.printf("Payment confirmation sent: %s%n", sendResult);
producer.shutdown();
}
}
- 订单完成
- 支付系统确认支付后,同步订单服务,完成订单。
public class OrderService {
public void completeOrder(String orderId) {
// 逻辑处理代码
System.out.println("Order completed for: " + orderId);
}
}
RocketMQ在不同场景下的使用技巧
- 流量削峰
- 在系统高峰期,通过RocketMQ缓存请求,避免因瞬时流量过大导致系统崩溃。
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 PeakShavingProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("PeakShavingProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("ShavingTopic", // topic
"ShavingTag", // tag
"ShavingKey123", // key
("Peak shaving request").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
SendResult sendResult = producer.send(msg);
System.out.printf("Peak shaving sent: %s%n", sendResult);
producer.shutdown();
}
}
- 数据同步
- RocketMQ可以帮助实现数据的异步同步,保证数据一致性。
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 DataSyncProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("DataSyncProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("SyncTopic", // topic
"SyncTag", // tag
"SyncKey123", // key
("Data sync request").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
SendResult sendResult = producer.send(msg);
System.out.printf("Data sync sent: %s%n", sendResult);
producer.shutdown();
}
}
- 异步处理
- 使用RocketMQ异步处理请求,可以显著提高系统响应速度和吞吐量。
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 AsyncRequestProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("AsyncProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("AsyncTopic", // topic
"AsyncTag", // tag
"AsyncKey123", // key
("Async request").getBytes(RemotingHelper.DEFAULT_CHARSET)); // body
SendResult sendResult = producer.send(msg);
System.out.printf("Async request sent: %s%n", sendResult);
producer.shutdown();
}
}
如何优化消息传递
- 消息压缩
- 通过压缩消息体,减少网络传输时间。
- 批量发送
- 多条消息合并发送,减少网络请求次数。
- 消息过滤
- 在消息消费端增加消息过滤逻辑,减少不必要的消息处理。
RocketMQ的基本架构
RocketMQ架构主要分为消息发送端、消息接收端、消息中间件(RocketMQ服务器)。
- 消息发送端
- 负责将消息发送到RocketMQ服务器。
- 消息接收端
- 负责从RocketMQ服务器拉取消息并进行消费。
- RocketMQ服务器
- 名字服务(Name Server):负责维护Topic信息。
- 消息服务(Broker):负责存储和转发消息。
- 客户端(Producer和Consumer):负责发送和接收消息。
名字服务与消息服务详解
- 名字服务(Name Server)
- 维护所有的Broker信息,并提供Broker的地址信息。
- 主要功能是提供Topic到Broker的路由信息。
- 消息服务(Broker)
- 负责存储消息。
- 负责转发消息到客户端。
- 实现消息的持久化、过滤、重试等机制。
高可用与可扩展性设计
- 高可用性
- NameServer集群化部署,保证服务的高可用性。
- Broker也可以配置集群,实现主备切换机制。
- 可扩展性
- 通过增加NameServer和Broker节点,提高系统吞吐量。
- 实现消息路由策略,提高系统的灵活性和适应性。
编写发送消息的代码
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 Producer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("TestTopic", // topic
"TagA", // tag
"OrderID188", // key
("Hello RocketMQ.").getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
System.out.printf("SendResult: %s%n", sendResult);
producer.shutdown();
}
}
编写接收消息的代码
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import java.util.List;
public class Consumer {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TestTopic", "TagA");
consumer.registerMessageListener((List<MessageExt> msgs, ConsumeOrderlyContext context) -> {
for (MessageExt msg : msgs) {
System.out.printf("Received message: %s%n", new String(msg.getBody()));
}
return ConsumeOrderlyStatus.SUCCESS;
});
consumer.start();
System.out.println("Consumer started.");
}
}
扩展功能代码示例
消息过滤示例
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.common.message.MessageExt;
import java.util.List;
public class ConsumerWithFilter {
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TestTopic", "*");
consumer.registerMessageListener((List<MessageExt> msgs, ConsumeOrderlyContext context) -> {
for (MessageExt msg : msgs) {
String tag = msg.getTopic() + ":" + msg.getTag();
if (tag.equals("TestTopic:TagA")) {
System.out.printf("Received message: %s%n", new String(msg.getBody()));
} else {
System.out.println("Message filtered out.");
}
}
return ConsumeOrderlyStatus.SUCCESS;
});
consumer.start();
System.out.println("Consumer started with message filtering.");
}
}
批量发送消息示例
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class ProducerWithBatch {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message[] msgs = new Message[10];
for (int i = 0; i < 10; i++) {
msgs[i] = new Message("TestTopic", // topic
"TagA", // tag
"OrderID" + i, // key
("Hello RocketMQ batch " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
}
SendResult sendResult = producer.send(msgs);
System.out.printf("SendResult: %s%n", sendResult);
producer.shutdown();
}
}
通过以上示例代码,可以详细了解RocketMQ的基本使用方式以及扩展功能的实现。
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦