为了账号安全,请及时绑定邮箱和手机立即绑定

RocketMQ源码项目实战:从入门到上手指南

概述

本文深入探讨了RocketMQ源码项目实战,从RocketMQ的基本概念、开发环境搭建到源码解析,详细介绍了RocketMQ的核心模块和运行机制。文章还通过实战案例展示了如何构建一个简单的消息系统,包括生产者发送消息、消费者接收消息以及监控与告警配置等步骤,旨在帮助读者全面掌握RocketMQ源码项目实战。

RocketMQ简介与环境搭建
RocketMQ是什么

RocketMQ是由阿里巴巴开源的一款分布式消息中间件。它具有高吞吐量、低延迟、高可用等特性,并且支持多种消息模式,如发布订阅、顺序消息、事务消息、定时消息等。RocketMQ广泛应用于阿里巴巴集团内的多个业务场景,如交易、物流配送、广告推送等领域。

RocketMQ的核心概念

核心概念介绍

  1. NameServer:NameServer是RocketMQ的注册中心,负责维护Broker的元数据信息,包括Broker的IP地址、端口号等信息。生产者和消费者通过NameServer获取Broker的信息。
  2. Broker:Broker是RocketMQ的消息代理服务端,负责接收、存储和转发消息。RocketMQ支持主从复制和集群模式,可以实现高可用和负载均衡。
  3. Producer:生产者负责向Broker发送消息。RocketMQ支持集群模式和广播模式两种发送消息的方式。
  4. Consumer:消费者负责从Broker中拉取消息。RocketMQ支持集群消费和广播消费两种消费方式。
  5. Topic:Topic是RocketMQ的消息主题,用于标识不同类型的消息。生产者发送消息时需要指定Topic,消费者订阅消息时也根据Topic进行订阅。
  6. Message:消息是RocketMQ的基本数据单元,包含消息体、消息标签、发送时间戳等信息。
  7. Order Message:顺序消息是RocketMQ支持的一种特性,可以保证消息的有序性,适用于一些对消息顺序要求较高的场景。
  8. Transaction Message:事务消息是一种特殊的事务消息,可以在发送消息后执行业务逻辑,RocketMQ会根据业务逻辑的执行结果决定消息是否提交或回滚。
  9. Message Queue:消息队列是RocketMQ中消息的物理存储结构,每个Topic可以包含多个消息队列。

源码示例

// 生产者发送消息
public class Producer {
    public static void main(String[] args) {
        // 创建生产者实例
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        // 设置NameServer地址
        producer.setNamesrvAddr("localhost:9876");
        // 启动生产者
        producer.start();

        // 创建消息
        Message msg = new Message("TopicTest", // Topic
                                  "TagA", // Tag
                                  "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET), // body
                                  null // 未指定Key
        );

        // 发送消息
        SendResult sendResult = producer.send(msg);
        System.out.printf("%s%n", sendResult);

        // 关闭生产者
        producer.shutdown();
    }
}
// 消费者消费消息
public class Consumer {
    public static void main(String[] args) {
        // 创建消费者实例
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
        // 设置NameServer地址
        consumer.setNamesrvAddr("localhost:9876");
        // 订阅Topic
        consumer.subscribe("TopicTest", "TagA");
        // 注册消息回调函数
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs) {
                    System.out.printf("Received message: %s%n", new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 启动消费者
        consumer.start();
    }
}
开发环境搭建

搭建步骤

  1. 下载RocketMQ:访问RocketMQ的GitHub主页(https://github.com/apache/rocketmq),下载RocketMQ的源码或压缩包
  2. 编译RocketMQ:下载RocketMQ源码后,可以通过Maven进行编译和打包。
    mvn clean install -DskipTests
  3. 启动NameServer:进入bin目录,运行NameServer的启动脚本。
    cd rocketmq-all-4.9.2/bin
    ./mqnamesrv
  4. 启动Broker:同样在bin目录下运行Broker的启动脚本。
    ./mqbroker -n localhost:9876 -c conf/broker-a.properties
  5. 编写生产者和消费者代码:使用IDEA或Eclipse等开发工具编写Java代码,实现生产者和消费者的逻辑。
  6. 运行生产者和消费者:运行Java程序,观察消息的发送和接收过程。

源码示例

// 启动NameServer
public class NameServerLauncher {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try {
            String hostIp = "127.0.0.1";
            int port = SystemPropertyUtil.getInt("name.server.port", 9876);
            ConfManager confManager = new ConfManager();

            executor.execute(new NamesrvController(confManager, hostIp, port));
        } catch (Exception e) {
            System.out.printf("Failed to start Name Server, cause: %s%n", e.getCause());
            System.exit(-1);
        }
        System.out.printf("RocketMQ-%s://%s:%d%n", Environment.NAMESRV_ADDR_PROPERTY, "127.0.0.1", 9876);
        System.exit(0);
    }
}
// 启动Broker
public class BrokerController {
    public BrokerController(BrokerConfig config, ServerConfig serverConfig, ClusterManager clusterManager,
                            TopicConfigManager topicConfigManager, MessageStore msgStore, NamesrvAddrList namesrvAddrList) {
        // 初始化Broker控制器
        ...
    }

    public void start() {
        // 启动Broker
        ...
    }

    public void shutdown() {
        // 关闭Broker
        ...
    }
}
快速上手RocketMQ

快速入门

  1. 创建生产者:创建一个DefaultMQProducer实例,设置生产者组名和NameServer地址。
  2. 创建消费者:创建一个DefaultMQPushConsumer实例,设置消费者组名和NameServer地址。
  3. 发送消息:使用生产者发送消息,指定消息的主题和标签。
  4. 接收消息:使用消费者接收消息,订阅指定的主题和标签。

源码示例

// 创建生产者
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();

// 发送消息
Message msg = new Message("TopicTest", // Topic
                          "TagA", // Tag
                          "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET), // body
                          null // 未指定Key
);
SendResult sendResult = producer.send(msg);
System.out.printf("SendResult: %s%n", sendResult);

// 关闭生产者
producer.shutdown();
// 创建消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("TopicTest", "TagA");

// 设置消息处理函数
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            System.out.printf("Received message: %s%n", new String(msg.getBody()));
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

// 启动消费者
consumer.start();

源码解析

public class DefaultMQProducer {
    // 创建生产者
    public DefaultMQProducer(String producerGroup) {
        // 初始化生产者
        ...
    }

    // 设置NameServer地址
    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    // 启动生产者
    public void start() {
        // 初始化生产者
        ...

        // 启动网络通信
        ...

        // 注册消息发送器
        ...
    }

    // 发送消息
    public SendResult send(Message msg) {
        // 获取Broker地址列表
        List<String> brokerAddresses = this.getBrokerAddrList();
        // 选择一个Broker发送消息
        String brokerAddress = this.selectOneMasterWithLeastMsg(brokerAddresses);
        // 构建消息发送请求
        SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
        // 发送消息请求
        SendResponse sendResponse = this.getDefaultMQProducerImpl.sendMessageSync(brokerAddress, requestHeader, msg);
        // 返回发送结果
        return new SendResult(sendResponse);
    }

    // 关闭生产者
    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}
public class DefaultMQPushConsumer {
    // 创建消费者
    public DefaultMQPushConsumer(String consumerGroup) {
        // 初始化消费者
        ...
    }

    // 设置NameServer地址
    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    // 订阅消息
    public void subscribe(String topic, String subscribeExpression) {
        // 订阅消息
        ...
    }

    // 注册消息监听器
    public void registerMessageListener(MessageListener listener) {
        // 注册消息监听器
        ...
    }

    // 启动消费者
    public void start() {
        // 初始化消费者
        ...

        // 启动网络通信
        ...

        // 注册消息接收器
        ...
    }

    // 关闭消费者
    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}
RocketMQ源码概览
RocketMQ源码结构讲解

源码结构

RocketMQ的源码结构分为以下几个主要模块:

  1. name-server:NameServer模块,负责维护Broker的元数据信息。
  2. broker:Broker模块,负责消息的存储和转发。
  3. client:客户端模块,包含生产者和消费者的相关代码。
  4. store:存储模块,负责消息的持久化存储。
  5. common:公共模块,包含一些通用的工具类和常量定义。
  6. tools:工具模块,包含一些辅助工具和脚本。
  7. remoting:网络通信模块,负责网络通信和消息传输。

源码文件示例

// NameServer核心代码
public class NamesrvController {
    public NamesrvController(ConfManager confManager, String hostIp, int listenPort) {
        // 初始化NameServer控制器
        ...
    }

    public void start() {
        // 启动NameServer
        ...
    }

    public void shutdown() {
        // 关闭NameServer
        ...
    }
}
// Broker核心代码
public class BrokerController {
    public BrokerController(BrokerConfig config, ServerConfig serverConfig, ClusterManager clusterManager,
                            TopicConfigManager topicConfigManager, MessageStore msgStore, NamesrvAddrList namesrvAddrList) {
        // 初始化Broker控制器
        ...
    }

    public void start() {
        // 启动Broker
        ...
    }

    public void shutdown() {
        // 关闭Broker
        ...
    }
}

源码解析

public class NettyRemotingServer {
    public NettyRemotingServer(String hostIp, int listenPort) {
        // 初始化Netty服务端
        ...
    }

    public void start() {
        // 启动Netty服务端
        ...
    }

    public void shutdown() {
        // 关闭Netty服务端
        ...
    }
}
public class MessageStore {
    public MessageStore(String storeConfigFile) {
        // 初始化MessageStore
        ...
    }

    public void start() {
        // 启动MessageStore
        ...
    }

    public void shutdown() {
        // 关闭MessageStore
        ...
    }
}
public class DefaultMQProducer {
    public DefaultMQProducer(String producerGroup) {
        // 初始化生产者
        ...
    }

    public void start() {
        // 启动生产者
        ...
    }

    public SendResult send(Message msg) {
        // 发送消息
        ...
    }

    public void shutdown() {
        // 关闭生产者
        ...
    }
}
public class DefaultMQPushConsumer {
    public DefaultMQPushConsumer(String consumerGroup) {
        // 初始化消费者
        ...
    }

    public void subscribe(String topic, String subscribeExpression) {
        // 订阅消息
        ...
    }

    public void registerMessageListener(MessageListener listener) {
        // 注册消息监听器
        ...
    }

    public void start() {
        // 启动消费者
        ...
    }

    public void shutdown() {
        // 关闭消费者
        ...
    }
}
主要模块介绍

NameServer模块

NameServer模块主要负责维护Broker的元数据信息。它会监听Broker的注册请求,并将这些信息存储在内存中。同时,NameServer会向Broker发送心跳包,以保持通信的连通性。

Broker模块

Broker模块是RocketMQ的核心模块,负责消息的存储和转发。Broker会接收生产者发送的消息,并将其存储到磁盘上。同时,Broker会根据消费者的订阅信息,将消息推送给对应的消费者。

客户端模块

客户端模块包含生产者和消费者的代码。生产者负责向Broker发送消息,而消费者则负责从Broker拉取消息。客户端模块会通过NameServer获取Broker的信息,并建立连接。

源码阅读技巧

阅读建议

  1. 熟悉RocketMQ的整体架构:了解RocketMQ的各个模块及其功能,包括NameServer、Broker、生产者、消费者等。
  2. 掌握RocketMQ的核心概念:熟悉RocketMQ的核心概念,如Topic、Message、Order Message等。
  3. 从源码中寻找关键逻辑:重点关注消息发送、消息接收和消息存储等核心逻辑。
  4. 理解网络通信机制:RocketMQ使用Netty进行网络通信,需要了解Netty的基本原理。
  5. 调试和日志分析:通过调试和查看日志,可以更好地理解RocketMQ的运行过程。
生产者发送消息流程详解
生产者发送消息的步骤

消息发送步骤

  1. 创建生产者实例:使用DefaultMQProducer创建生产者实例,并设置生产者组名。
  2. 设置NameServer地址:通过setNamesrvAddr方法设置NameServer的地址。
  3. 启动生产者:调用start方法启动生产者。
  4. 创建消息:使用Message类创建消息,指定消息的主题、标签、消息体等信息。
  5. 发送消息:调用send方法发送消息。
  6. 关闭生产者:调用shutdown方法关闭生产者。

源码解析发送消息的过程

public class DefaultMQProducer {
    // 创建生产者
    public DefaultMQProducer(String producerGroup) {
        // 初始化生产者
        ...
    }

    // 设置NameServer地址
    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    // 启动生产者
    public void start() {
        // 初始化生产者
        ...

        // 启动网络通信
        ...

        // 注册消息发送器
        ...
    }

    // 发送消息
    public SendResult send(Message msg) {
        // 获取Broker地址列表
        List<String> brokerAddresses = this.getBrokerAddrList();
        // 选择一个Broker发送消息
        String brokerAddress = this.selectOneMasterWithLeastMsg(brokerAddresses);
        // 构建消息发送请求
        SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
        // 发送消息请求
        SendResponse sendResponse = this.getDefaultMQProducerImpl.sendMessageSync(brokerAddress, requestHeader, msg);
        // 返回发送结果
        return new SendResult(sendResponse);
    }

    // 关闭生产者
    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}

常见问题及解决方法

  1. 消息发送失败:检查生产者的配置是否正确,包括NameServer地址、生产者组名等。同时,检查Broker是否正常运行。
  2. 消息发送缓慢:优化生产者的发送性能,例如使用异步发送模式。
  3. 消息丢失:确保消息的持久化配置正确,RocketMQ支持消息的持久化存储,可以防止消息丢失。

源码示例

public class DefaultMQProducer {
    public DefaultMQProducer(String producerGroup) {
        // 初始化生产者
        ...
    }

    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    public void start() {
        // 初始化生产者
        ...

        // 启动网络通信
        ...

        // 注册消息发送器
        ...
    }

    public SendResult send(Message msg) {
        // 获取Broker地址列表
        List<String> brokerAddresses = this.getBrokerAddrList();
        // 选择一个Broker发送消息
        String brokerAddress = this.selectOneMasterWithLeastMsg(brokerAddresses);
        // 构建消息发送请求
        SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
        // 发送消息请求
        SendResponse sendResponse = this.getDefaultMQProducerImpl.sendMessageSync(brokerAddress, requestHeader, msg);
        // 返回发送结果
        return new SendResult(sendResponse);
    }

    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}
消费者接收消息流程详解
消费者接收消息的步骤

消息接收步骤

  1. 创建消费者实例:使用DefaultMQPushConsumer创建消费者实例,并设置消费者组名。
  2. 设置NameServer地址:通过setNamesrvAddr方法设置NameServer的地址。
  3. 订阅消息:调用subscribe方法订阅指定的主题和标签。
  4. 注册消息监听器:通过registerMessageListener方法注册一个消息监听器,用于处理接收到的消息。
  5. 启动消费者:调用start方法启动消费者。
  6. 关闭消费者:调用shutdown方法关闭消费者。

源码解析接收消息的过程

public class DefaultMQPushConsumer {
    // 创建消费者
    public DefaultMQPushConsumer(String consumerGroup) {
        // 初始化消费者
        ...
    }

    // 设置NameServer地址
    public void setNamesrvAddr(String namesrvAddr) {
        this.namesrvAddr = namesrvAddr;
    }

    // 订阅消息
    public void subscribe(String topic, String subscribeExpression) {
        // 订阅消息
        ...
    }

    // 注册消息监听器
    public void registerMessageListener(MessageListener listener) {
        // 注册消息监听器
        ...
    }

    // 启动消费者
    public void start() {
        // 初始化消费者
        ...

        // 启动网络通信
        ...

        // 注册消息接收器
        ...
    }

    // 关闭消费者
    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}

消费者异常处理机制

消息处理异常

  1. 消息处理异常:如果在消息处理过程中发生异常,可以通过消息监听器抛出异常。RocketMQ会记录异常信息,并根据异常类型进行处理。
  2. 消息重试机制:RocketMQ支持消息重试机制,如果消息处理失败,可以设置重试次数和重试间隔时间。
  3. 消息回溯机制:如果消息处理失败,可以通过消息回溯机制重新处理之前的消息。

源码示例

public class DefaultMQPushConsumer {
    public void registerMessageListener(MessageListener listener) {
        // 注册消息监听器
        this.messageListener = listener;
    }

    public void start() {
        // 启动网络通信
        ...

        // 注册消息接收器
        this.pullMessageService.start();
    }

    public void shutdown() {
        // 关闭网络通信
        ...

        // 释放资源
        ...
    }
}
public class MessageListenerConcurrently implements MessageListener {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        for (MessageExt msg : msgs) {
            try {
                // 处理消息
                ...
            } catch (Exception e) {
                // 消息处理异常
                ...
            }
        }
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
}
RocketMQ集群部署与监控
集群部署方案

集群部署步骤

  1. 部署NameServer:部署多个NameServer实例,实现高可用。
  2. 部署Broker:部署多个Broker实例,实现负载均衡。
  3. 配置集群模式:在Broker配置文件中,设置集群模式。
  4. 启动NameServer和Broker:启动部署好的NameServer和Broker实例。
  5. 配置生产者和消费者:配置生产者和消费者的集群模式。

集群部署示例

# Broker配置文件
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
brokerRole = ASYNC_MASTER
namesrvAddr = localhost:9876
storePathRootDir = /data/rocketmq/store
storePathCommitLog = /data/rocketmq/store/commitlog
storePathConsumeQueue = /data/rocketmq/store/consumequeue
storePathIndex = /data/rocketmq/store/index
messageStoreConfig = /data/rocketmq/conf/messageStoreConfig.json
brokerConfig = /data/rocketmq/conf/brokerConfig.json
// 生产者配置
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
producer.setNamesrvAddr("localhost:9876");
producer.setSendMsgBatch(false);
producer.setSendMsgTimeout(3000);
producer.setInstanceName("Producer");
producer.start();

// 消费者配置
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.setConsumeMessageBatchMaxSize(1);
consumer.setConsumeThreadMin(1);
consumer.setConsumeThreadMax(16);
consumer.setConsumeTimeout(3000);
consumer.setInstanceName("Consumer");
consumer.start();
监控与告警配置

监控方案

  1. 监控RocketMQ的内置指标:RocketMQ提供了内置的监控指标,可以通过JMX接口获取。
  2. 配置监控工具:使用Prometheus等监控工具,监控RocketMQ的各项指标。
  3. 配置告警规则:根据监控数据,配置告警规则,实现告警通知。

监控示例

public class RocketMQMonitor {
    public static void main(String[] args) {
        // 初始化监控器
        RocketMQMonitor monitor = new RocketMQMonitor();

        // 获取NameServer的监控数据
        List<NamesrvController> nameServers = monitor.getNamesrvControllers();
        for (NamesrvController nameServer : nameServers) {
            System.out.printf("NameServer: %s, Number of Brokers: %d%n", nameServer.getControllerName(), nameServer.getNumberOfBrokers());
        }

        // 获取Broker的监控数据
        List<BrokerController> brokers = monitor.getBrokerControllers();
        for (BrokerController broker : brokers) {
            System.out.printf("Broker: %s, Number of Messages: %d, Size of Messages: %d%n", broker.getBrokerName(), broker.getNumberOfMessages(), broker.getSizeOfMessages());
        }
    }
}

告警配置

  1. 配置告警规则:定义监控告警规则,如Broker消息积压超过一定数量。
  2. 配置告警通知:配置告警通知方式,如邮件、短信、钉钉等。
  3. 监控和维护:定期检查监控数据和告警通知,及时处理问题。
# 告警配置文件
alertEmail = admin@example.com
alertPhone = 12345678901
alertDingTalk = https://www.dingtalk.com/
alertRule = broker.messageQueue.size > 10000
alertInterval = 300
常见问题排查方法

排查步骤

  1. 检查配置文件:确保NameServer、Broker、生产者和消费者配置正确。
  2. 查看日志信息:通过日志文件,查看RocketMQ的运行状态和异常信息。
  3. 监控数据分析:通过监控工具,分析RocketMQ的各项指标。
  4. 网络通信检查:检查网络通信是否正常,确保NameServer、Broker和客户端之间的通信畅通。
  5. 重启服务:如果以上方法都无法解决问题,可以尝试重启NameServer、Broker和客户端服务。

排查示例

# 查看NameServer的日志
tail -f /data/rocketmq/logs/name-srv.log

# 查看Broker的日志
tail -f /data/rocketmq/logs/broker.log

# 查看生产者的日志
tail -f /data/rocketmq/logs/producer.log

# 查看消费者的日志
tail -f /data/rocketmq/logs/consumer.log
实战案例:构建一个简单的消息系统
实战项目需求分析

案例需求

  1. 生产者发送消息:实现一个生产者,每秒发送一条消息。
  2. 消费者接收消息:实现一个消费者,接收并处理消息。
  3. 持久化消息:确保消息持久化存储,防止消息丢失。
  4. 监控与告警:监控消息系统的运行状态,并配置告警规则。

案例架构

  1. 生产者:每秒发送一条消息。
  2. 消费者:接收消息,并处理消息。
  3. Broker:存储和转发消息。
  4. NameServer:注册和管理Broker。
项目实战步骤

实战步骤

  1. 创建生产者:编写生产者代码,每秒发送一条消息。
  2. 创建消费者:编写消费者代码,接收并处理消息。
  3. 启动NameServer和Broker:启动NameServer和Broker,确保消息系统的运行。
  4. 监控和告警配置:配置监控工具和告警规则。

生产者代码示例

public class MessageProducer {
    public static void main(String[] args) throws MQClientException {
        // 创建生产者实例
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        // 设置NameServer地址
        producer.setNamesrvAddr("localhost:9876");
        // 启动生产者
        producer.start();

        // 设置消息发送间隔
        long t = System.currentTimeMillis();
        while (true) {
            // 创建消息
            Message msg = new Message("TopicTest", // Topic
                                      "TagA", // Tag
                                      ("Hello RocketMQ, message index: " + i).getBytes(RemotingHelper.DEFAULT_CHARSET), // body
                                      null // 未指定Key
            );
            // 发送消息
            SendResult sendResult = producer.send(msg);
            System.out.printf("%s%n", sendResult);

            // 计算消息发送间隔
            long now = System.currentTimeMillis();
            long diff = now - t;
            if (diff < 1000) {
                try {
                    Thread.sleep(1000 - diff);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                t = now;
            }
        }
    }
}

消费者代码示例

public class MessageConsumer {
    public static void main(String[] args) throws MQClientException {
        // 创建消费者实例
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
        // 设置NameServer地址
        consumer.setNamesrvAddr("localhost:9876");
        // 订阅消息
        consumer.subscribe("TopicTest", "TagA");
        // 注册消息监听器
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs) {
                    System.out.printf("Received message: %s%n", new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 启动消费者
        consumer.start();
    }
}
测试与优化

测试步骤

  1. 启动NameServer和Broker:确保NameServer和Broker正常运行。
  2. 启动生产者和消费者:启动生产者和消费者,观察消息的发送和接收过程。
  3. 监控和告警配置:配置监控工具和告警规则,监控消息系统的运行状态。

测试示例

# 启动NameServer
cd rocketmq-all-4.9.2/bin
./mqnamesrv

# 启动Broker
./mqbroker -n localhost:9876 -c conf/broker-a.properties

# 启动生产者
java -cp rocketmq-all-4.9.2/lib/*:. MessageProducer

# 启动消费者
java -cp rocketmq-all-4.9.2/lib/*:. MessageConsumer

优化建议

  1. 优化消息发送性能:使用异步发送模式,提高消息发送性能。
  2. 优化消息接收性能:使用批量接收模式,提高消息接收性能。
  3. 优化消息存储性能:优化消息存储配置,提高消息存储性能。

优化示例

public class MessageProducer {
    public static void main(String[] args) throws MQClientException {
        // 创建生产者实例
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        // 设置NameServer地址
        producer.setNamesrvAddr("localhost:9876");
        // 设置发送模式为异步发送
        producer.setSendMsgBatch(true);
        // 启动生产者
        producer.start();

        // 设置消息发送间隔
        long t = System.currentTimeMillis();
        while (true) {
            // 创建消息
            Message msg = new Message("TopicTest", // Topic
                                      "TagA", // Tag
                                      ("Hello RocketMQ, message index: " + i).getBytes(RemotingHelper.DEFAULT_CHARSET), // body
                                      null // 未指定Key
            );
            // 发送消息
            producer.send(msg);

            // 计算消息发送间隔
            long now = System.currentTimeMillis();
            long diff = now - t;
            if (diff < 1000) {
                try {
                    Thread.sleep(1000 - diff);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                t = now;
            }
        }
    }
}
public class MessageConsumer {
    public static void main(String[] args) throws MQClientException {
        // 创建消费者实例
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
        // 设置NameServer地址
        consumer.setNamesrvAddr("localhost:9876");
        // 设置接收模式为批量接收
        consumer.setConsumeMessageBatchMaxSize(10);
        // 订阅消息
        consumer.subscribe("TopicTest", "TagA");
        // 注册消息监听器
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs) {
                    System.out.printf("Received message: %s%n", new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 启动消费者
        consumer.start();
    }
}

监控与告警示例

public class RocketMQMonitor {
    public static void main(String[] args) {
        // 初始化监控器
        RocketMQMonitor monitor = new RocketMQMonitor();

        // 获取NameServer的监控数据
        List<NamesrvController> nameServers = monitor.getNamesrvControllers();
        for (NamesrvController nameServer : nameServers) {
            System.out.printf("NameServer: %s, Number of Brokers: %d%n", nameServer.getControllerName(), nameServer.getNumberOfBrokers());
        }

        // 获取Broker的监控数据
        List<BrokerController> brokers = monitor.getBrokerControllers();
        for (BrokerController broker : brokers) {
            System.out.printf("Broker: %s, Number of Messages: %d, Size of Messages: %d%n", broker.getBrokerName(), broker.getNumberOfMessages(), broker.getSizeOfMessages());
        }
    }
}
# 告警配置文件
alertEmail = admin@example.com
alertPhone = 12345678901
alertDingTalk = https://www.dingtalk.com/
alertRule = broker.messageQueue.size > 10000
alertInterval = 300
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消