From Zero to Running RocketMQ: My First Producer‑Consumer Walkthrough
This article chronicles my step‑by‑step journey of learning Apache RocketMQ, from downloading the source and building it with Maven, configuring mirrors, launching NameServer, Broker, Producer and Consumer on Windows, to exploring the system’s architecture and design principles.
I was a complete beginner with RocketMQ, so I decided to record my cold‑start experience step by step.
First, I visited the official site http://rocketmq.apache.org/ , clicked the large Getting Started button and opened the quick‑start page, which provided the 4.8.0 source zip URL:
After downloading, I opened the Maven‑based Java project in IntelliJ IDEA.
> mvn -Prelease-all -DskipTests clean install -U
> cd distribution/target/rocketmq-4.8.0/rocketmq-4.8.0The build failed because Maven could not download many central‑repo JARs. I edited my settings.xml to use Alibaba’s mirror:
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<mirrorOf>central</mirrorOf>
</mirror>With the mirror configured the build succeeded.
Next, I followed the Windows quick‑start guide, which lists four startup scripts:
## Start Name Server
.bin\mqnamesrv.cmd
## Start Broker
.bin\mqbroker.cmd -n localhost:9876 autoCreateTopicEnable=true
## Send Messages
.bin\tools.cmd org.apache.rocketmq.example.quickstart.Producer
## Receive Messages
.bin\tools.cmd org.apache.rocketmq.example.quickstart.ConsumerI executed the scripts from IDEA, which simply invoke the main methods of the corresponding classes.
The simplified producer main method looks like this:
DefaultMQProducer producer = new DefaultMQProducer("example");
producer.start();
for (int i = 0; i < 1000; i++) {
Message msg = new Message(...);
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
}Running it prints a series of SendResult lines, confirming that messages are being produced.
The consumer main method is similarly straightforward:
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("example");
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
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.start();After starting the consumer I see a stream of messages being consumed, confirming end‑to‑end functionality.
In summary, I launched a NameServer (port 9876), a Broker that points to that NameServer, a Producer that sent many messages, and a Consumer that received them. Both Producer and Consumer require the environment variable NAMESRV_ADDR=localhost:9876.
The official architecture diagram is similar but includes clustering details:
Key components are:
Producer : publishes messages to a chosen broker queue.
Consumer : pulls or pushes messages from the broker.
NameServer : a lightweight topic‑routing registry that supports dynamic broker registration.
BrokerServer : handles storage, delivery and query, and consists of Remoting Module, Client Manager, Store Service, HA Service, and Index Service.
The deployment architecture shown in the docs matches the order I followed (NameServer → Broker → Producer/Consumer) and also explains optional topic creation.
Design principles are covered in a separate document and consist of six parts: message storage, communication mechanism, message filtering, load balancing, transactional messages, and message query.
For example, the storage section explains that RocketMQ uses MappedByteBuffer (NIO’s FileChannel) to memory‑map files, avoiding the copy overhead of traditional I/O and enabling high‑throughput reads and writes.
RocketMQ mainly reads and writes files via MappedByteBuffer . By mapping physical files directly into user‑space memory (the mmap technique), it eliminates the performance cost of copying data between kernel buffers and user buffers, greatly improving file I/O efficiency. Because of this memory‑mapping approach, RocketMQ stores data in fixed‑length structures that can be mapped in one go.
Understanding these low‑level mechanisms (IO models, memory‑mapping, sequential disk access, page cache, synchronous vs. asynchronous flushing) helps you grasp how the higher‑level messaging features are built.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
